Skip to content

Commit 39221f8

Browse files
GradiTratcher
authored andcommitted
Added support for Set-Cookie's SameSite attribute in ResponseCookieCollection (#299)
1 parent 569f1c8 commit 39221f8

File tree

4 files changed

+55
-3
lines changed

4 files changed

+55
-3
lines changed

src/Microsoft.Owin/CookieOptions.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,12 @@ public CookieOptions()
4747
/// </summary>
4848
/// <returns>true if a cookie is accessible by client-side script; otherwise, false.</returns>
4949
public bool HttpOnly { get; set; }
50+
51+
/// <summary>
52+
/// Gets or sets a value that indicates on which requests client should or should not send cookie back to the server.
53+
/// Set to null to do not include SameSite attribute at all.
54+
/// </summary>
55+
/// <returns>SameSite attribute value or null if attribute must not be set.</returns>
56+
public SameSiteMode? SameSite { get; set; }
5057
}
5158
}

src/Microsoft.Owin/Microsoft.Owin.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@
9595
<Compile Include="Infrastructure\SystemClock.cs" />
9696
<Compile Include="Infrastructure\WebUtils.cs" />
9797
<Compile Include="ResponseCookieCollection.cs" />
98+
<Compile Include="SameSiteMode.cs" />
9899
<Compile Include="Security\AuthenticateResult.cs" />
99100
<Compile Include="Security\AuthenticationDescription.cs" />
100101
<Compile Include="Extensions\IntegratedPipelineExtensions.cs" />

src/Microsoft.Owin/ResponseCookieCollection.cs

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ public void Append(string key, string value, CookieOptions options)
5656
bool domainHasValue = !string.IsNullOrEmpty(options.Domain);
5757
bool pathHasValue = !string.IsNullOrEmpty(options.Path);
5858
bool expiresHasValue = options.Expires.HasValue;
59+
bool sameSiteHasValue = options.SameSite.HasValue;
5960

6061
string setCookieValue = string.Concat(
6162
Uri.EscapeDataString(key),
@@ -66,10 +67,12 @@ public void Append(string key, string value, CookieOptions options)
6667
!pathHasValue ? null : "; path=",
6768
!pathHasValue ? null : options.Path,
6869
!expiresHasValue ? null : "; expires=",
69-
!expiresHasValue ? null : options.Expires.Value.ToString("ddd, dd-MMM-yyyy HH:mm:ss ", CultureInfo.InvariantCulture) + "GMT",
70+
!expiresHasValue ? null : options.Expires.Value.ToString("ddd, dd-MMM-yyyy HH:mm:ss \\G\\M\\T", CultureInfo.InvariantCulture),
7071
!options.Secure ? null : "; secure",
71-
!options.HttpOnly ? null : "; HttpOnly");
72-
Headers.AppendValues("Set-Cookie", setCookieValue);
72+
!options.HttpOnly ? null : "; HttpOnly",
73+
!sameSiteHasValue ? null : "; SameSite=",
74+
!sameSiteHasValue ? null : GetStringRepresentationOfSameSite(options.SameSite.Value));
75+
Headers.AppendValues(Constants.Headers.SetCookie, setCookieValue);
7376
}
7477

7578
/// <summary>
@@ -138,5 +141,25 @@ public void Delete(string key, CookieOptions options)
138141
Expires = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc),
139142
});
140143
}
144+
145+
/// <summary>
146+
/// Analogous to ToString() but without boxing so
147+
/// we can save a bit of memory.
148+
/// </summary>
149+
private static string GetStringRepresentationOfSameSite(SameSiteMode siteMode)
150+
{
151+
switch (siteMode)
152+
{
153+
case SameSiteMode.None:
154+
return "None";
155+
case SameSiteMode.Lax:
156+
return "Lax";
157+
case SameSiteMode.Strict:
158+
return "Strict";
159+
default:
160+
throw new ArgumentOutOfRangeException("siteMode",
161+
string.Format(CultureInfo.InvariantCulture, "Unexpected SameSiteMode value: {0}", siteMode));
162+
}
163+
}
141164
}
142165
}

src/Microsoft.Owin/SameSiteMode.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
namespace Microsoft.Owin
2+
{
3+
/// <summary>
4+
/// Indicates if the client should include a cookie on "same-site" or "cross-site" requests.
5+
/// </summary>
6+
public enum SameSiteMode
7+
{
8+
/// <summary>
9+
/// Indicates the client should send the cookie with every requests coming from any origin.
10+
/// </summary>
11+
None = 0,
12+
/// <summary>
13+
/// Indicates the client should send the cookie with "same-site" requests, and with "cross-site" top-level navigations.
14+
/// </summary>
15+
Lax,
16+
/// <summary>
17+
/// Indicates the client should only send the cookie with "same-site" requests.
18+
/// </summary>
19+
Strict
20+
}
21+
}

0 commit comments

Comments
 (0)