Skip to content
This repository was archived by the owner on Nov 22, 2018. It is now read-only.

Commit df41fd8

Browse files
author
Nate McMaster
committed
Replace the ConfigureCookieOptions action property with the CookieBuilder
1 parent cfe0e30 commit df41fd8

File tree

9 files changed

+218
-217
lines changed

9 files changed

+218
-217
lines changed

src/Microsoft.AspNetCore.Antiforgery/AntiforgeryOptions.cs

Lines changed: 83 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -14,102 +14,123 @@ public class AntiforgeryOptions
1414
private const string AntiforgeryTokenFieldName = "__RequestVerificationToken";
1515
private const string AntiforgeryTokenHeaderName = "RequestVerificationToken";
1616

17-
private string _cookieName;
1817
private string _formFieldName = AntiforgeryTokenFieldName;
1918

19+
private CookieBuilder _cookieBuilder = new CookieBuilder
20+
{
21+
SameSite = SameSiteMode.Strict,
22+
HttpOnly = true
23+
};
24+
2025
/// <summary>
2126
/// The default cookie prefix, which is ".AspNetCore.Antiforgery.".
2227
/// </summary>
2328
public static readonly string DefaultCookiePrefix = ".AspNetCore.Antiforgery.";
2429

2530
/// <summary>
26-
/// Specifies the name of the cookie that is used by the antiforgery system.
31+
/// Determines the settings used to create the antiforgery cookies.
2732
/// </summary>
2833
/// <remarks>
29-
/// If an explicit name is not provided, the system will automatically generate a
34+
/// <para>
35+
/// If an explicit <see cref="CookieBuilder.Name"/> is not provided, the system will automatically generate a
3036
/// unique name that begins with <see cref="DefaultCookiePrefix"/>.
37+
/// </para>
38+
/// <para>
39+
/// <see cref="CookieBuilder.SameSite"/> defaults to <see cref="SameSiteMode.Strict"/>.
40+
/// <see cref="CookieBuilder.HttpOnly"/> defaults to <c>true</c>.
41+
/// </para>
3142
/// </remarks>
32-
public string CookieName
43+
public CookieBuilder Cookie
3344
{
34-
get
35-
{
36-
return _cookieName;
37-
}
38-
set
39-
{
40-
if (value == null)
41-
{
42-
throw new ArgumentNullException(nameof(value));
43-
}
44-
45-
_cookieName = value;
46-
}
45+
get => _cookieBuilder;
46+
set => _cookieBuilder = value ?? throw new ArgumentNullException(nameof(value));
4747
}
4848

4949
/// <summary>
50-
/// This is obsolete and will be removed in a future version.
51-
/// The recommended alternative is to use ConfigureCookieOptions.
52-
/// The path set on the cookie. If set to <c>null</c>, the "path" attribute on the cookie is set to the current
53-
/// request's <see cref="HttpRequest.PathBase"/> value. If the value of <see cref="HttpRequest.PathBase"/> is
54-
/// <c>null</c> or empty, then the "path" attribute is set to the value of <see cref="CookieOptions.Path"/>.
50+
/// Specifies the name of the antiforgery token field that is used by the antiforgery system.
5551
/// </summary>
56-
[Obsolete("This is obsolete and will be removed in a future version. The recommended alternative is to use ConfigureCookieOptions.")]
57-
public PathString? CookiePath { get; set; }
52+
public string FormFieldName
53+
{
54+
get => _formFieldName;
55+
set => _formFieldName = value ?? throw new ArgumentNullException(nameof(value));
56+
}
5857

5958
/// <summary>
60-
/// This is obsolete and will be removed in a future version.
61-
/// The recommended alternative is to use ConfigureCookieOptions.
62-
/// The domain set on the cookie. By default its <c>null</c> which results in the "domain" attribute not being set.
59+
/// Specifies the name of the header value that is used by the antiforgery system. If <c>null</c> then
60+
/// antiforgery validation will only consider form data.
6361
/// </summary>
64-
[Obsolete("This is obsolete and will be removed in a future version. The recommended alternative is to use ConfigureCookieOptions.")]
65-
public string CookieDomain { get; set; }
62+
public string HeaderName { get; set; } = AntiforgeryTokenHeaderName;
6663

6764
/// <summary>
68-
/// Configures the <see cref="CookieOptions"/> of the antiforgery cookies. Without additional configuration, the
69-
/// default values antiforgery cookie options are true for <see cref="CookieOptions.HttpOnly"/>, null for
70-
/// <see cref="CookieOptions.Domain"/> and <see cref="SameSiteMode.Strict"/> for <see cref="CookieOptions.SameSite"/>.
65+
/// Specifies whether to suppress the generation of X-Frame-Options header
66+
/// which is used to prevent ClickJacking. By default, the X-Frame-Options
67+
/// header is generated with the value SAMEORIGIN. If this setting is 'true',
68+
/// the X-Frame-Options header will not be generated for the response.
7169
/// </summary>
72-
public Action<HttpContext, CookieOptions> ConfigureCookieOptions { get; set; }
70+
public bool SuppressXFrameOptionsHeader { get; set; }
7371

72+
#region Obsolete API
7473
/// <summary>
75-
/// Specifies the name of the antiforgery token field that is used by the antiforgery system.
74+
/// <para>
75+
/// This property is obsolete and will be removed in a future version. The recommended alternative is <seealso cref="CookieBuilder.Name"/> on <see cref="Cookie"/>.
76+
/// </para>
77+
/// <para>
78+
/// Specifies the name of the cookie that is used by the antiforgery system.
79+
/// </para>
7680
/// </summary>
77-
public string FormFieldName
78-
{
79-
get
80-
{
81-
return _formFieldName;
82-
}
83-
set
84-
{
85-
if (value == null)
86-
{
87-
throw new ArgumentNullException(nameof(value));
88-
}
81+
/// <remarks>
82+
/// If an explicit name is not provided, the system will automatically generate a
83+
/// unique name that begins with <see cref="DefaultCookiePrefix"/>.
84+
/// </remarks>
85+
[Obsolete("This property is obsolete and will be removed in a future version. The recommended alternative is " + nameof(Cookie) + "." + nameof(CookieBuilder.Name) + ".")]
86+
public string CookieName { get => Cookie.Name; set => Cookie.Name = value; }
8987

90-
_formFieldName = value;
91-
}
92-
}
88+
/// <summary>
89+
/// <para>
90+
/// This property is obsolete and will be removed in a future version. The recommended alternative is <seealso cref="CookieBuilder.Path"/> on <see cref="Cookie"/>.
91+
/// </para>
92+
/// <para>
93+
/// The path set on the cookie. If set to <c>null</c>, the "path" attribute on the cookie is set to the current
94+
/// request's <see cref="HttpRequest.PathBase"/> value. If the value of <see cref="HttpRequest.PathBase"/> is
95+
/// <c>null</c> or empty, then the "path" attribute is set to the value of <see cref="CookieOptions.Path"/>.
96+
/// </para>
97+
/// </summary>
98+
[Obsolete("This property is obsolete and will be removed in a future version. The recommended alternative is " + nameof(Cookie) + "." + nameof(CookieBuilder.Path) + ".")]
99+
public PathString? CookiePath { get => Cookie.Path; set => Cookie.Path = value; }
93100

94101
/// <summary>
95-
/// Specifies the name of the header value that is used by the antiforgery system. If <c>null</c> then
96-
/// antiforgery validation will only consider form data.
102+
/// <para>
103+
/// This property is obsolete and will be removed in a future version. The recommended alternative is <seealso cref="CookieBuilder.Domain"/> on <see cref="Cookie"/>.
104+
/// </para>
105+
/// <para>
106+
/// The domain set on the cookie. By default its <c>null</c> which results in the "domain" attribute not being set.
107+
/// </para>
97108
/// </summary>
98-
public string HeaderName { get; set; } = AntiforgeryTokenHeaderName;
109+
[Obsolete("This property is obsolete and will be removed in a future version. The recommended alternative is " + nameof(Cookie) + "." + nameof(CookieBuilder.Domain) + ".")]
110+
public string CookieDomain { get => Cookie.Domain; set => Cookie.Domain = value; }
111+
99112

100113
/// <summary>
114+
/// <para>
115+
/// This property is obsolete and will be removed in a future version.
116+
/// The recommended alternative is to set <seealso cref="CookieBuilder.SecurePolicy"/> on <see cref="Cookie"/>.
117+
/// </para>
118+
/// <para>
119+
/// <c>true</c> is equivalent to <see cref="CookieSecurePolicy.Always"/>.
120+
/// <c>false</c> is equivalent to <see cref="CookieSecurePolicy.None"/>.
121+
/// </para>
122+
/// <para>
101123
/// Specifies whether SSL is required for the antiforgery system
102124
/// to operate. If this setting is 'true' and a non-SSL request
103125
/// comes into the system, all antiforgery APIs will fail.
126+
/// </para>
104127
/// </summary>
105-
public bool RequireSsl { get; set; }
106-
107-
/// <summary>
108-
/// Specifies whether to suppress the generation of X-Frame-Options header
109-
/// which is used to prevent ClickJacking. By default, the X-Frame-Options
110-
/// header is generated with the value SAMEORIGIN. If this setting is 'true',
111-
/// the X-Frame-Options header will not be generated for the response.
112-
/// </summary>
113-
public bool SuppressXFrameOptionsHeader { get; set; }
128+
[Obsolete("This property is obsolete and will be removed in a future version. The recommended alternative is to set " + nameof(Cookie) + "." + nameof(CookieBuilder.SecurePolicy) + ".")]
129+
public bool RequireSsl
130+
{
131+
get => Cookie.SecurePolicy == CookieSecurePolicy.Always;
132+
set => Cookie.SecurePolicy = value ? CookieSecurePolicy.Always : CookieSecurePolicy.None;
133+
}
134+
#endregion
114135
}
115-
}
136+
}

src/Microsoft.AspNetCore.Antiforgery/Internal/AntiforgeryOptionsSetup.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ public AntiforgeryOptionsSetup(IOptions<DataProtectionOptions> dataProtectionOpt
1818

1919
public static void ConfigureOptions(AntiforgeryOptions options, DataProtectionOptions dataProtectionOptions)
2020
{
21-
if (options.CookieName == null)
21+
if (options.Cookie.Name == null)
2222
{
2323
var applicationId = dataProtectionOptions.ApplicationDiscriminator ?? string.Empty;
24-
options.CookieName = AntiforgeryOptions.DefaultCookiePrefix + ComputeCookieName(applicationId);
24+
options.Cookie.Name = AntiforgeryOptions.DefaultCookiePrefix + ComputeCookieName(applicationId);
2525
}
2626
}
2727

src/Microsoft.AspNetCore.Antiforgery/Internal/DefaultAntiforgery.cs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ public async Task<bool> IsRequestValidAsync(HttpContext httpContext)
111111
var tokens = await _tokenStore.GetRequestTokensAsync(httpContext);
112112
if (tokens.CookieToken == null)
113113
{
114-
_logger.MissingCookieToken(_options.CookieName);
114+
_logger.MissingCookieToken(_options.Cookie.Name);
115115
return false;
116116
}
117117

@@ -160,7 +160,7 @@ public async Task ValidateRequestAsync(HttpContext httpContext)
160160
if (tokens.CookieToken == null)
161161
{
162162
throw new AntiforgeryValidationException(
163-
Resources.FormatAntiforgery_CookieToken_MustBeProvided(_options.CookieName));
163+
Resources.FormatAntiforgery_CookieToken_MustBeProvided(_options.Cookie.Name));
164164
}
165165

166166
if (tokens.RequestToken == null)
@@ -265,12 +265,11 @@ private void SaveCookieTokenAndHeader(HttpContext httpContext, string cookieToke
265265

266266
private void CheckSSLConfig(HttpContext context)
267267
{
268-
if (_options.RequireSsl && !context.Request.IsHttps)
268+
if (_options.Cookie.SecurePolicy == CookieSecurePolicy.Always && !context.Request.IsHttps)
269269
{
270-
throw new InvalidOperationException(Resources.FormatAntiforgeryWorker_RequireSSL(
271-
nameof(AntiforgeryOptions),
272-
nameof(AntiforgeryOptions.RequireSsl),
273-
"true"));
270+
throw new InvalidOperationException(Resources.FormatAntiforgery_RequiresSSL(
271+
string.Join(".", nameof(AntiforgeryOptions), nameof(AntiforgeryOptions.Cookie), nameof(CookieBuilder.SecurePolicy)),
272+
nameof(CookieSecurePolicy.Always)));
274273
}
275274
}
276275

src/Microsoft.AspNetCore.Antiforgery/Internal/DefaultAntiforgeryTokenStore.cs

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public string GetCookieToken(HttpContext httpContext)
2828
{
2929
Debug.Assert(httpContext != null);
3030

31-
var requestCookie = httpContext.Request.Cookies[_options.CookieName];
31+
var requestCookie = httpContext.Request.Cookies[_options.Cookie.Name];
3232
if (string.IsNullOrEmpty(requestCookie))
3333
{
3434
// unable to find the cookie.
@@ -42,7 +42,7 @@ public async Task<AntiforgeryTokenSet> GetRequestTokensAsync(HttpContext httpCon
4242
{
4343
Debug.Assert(httpContext != null);
4444

45-
var cookieToken = httpContext.Request.Cookies[_options.CookieName];
45+
var cookieToken = httpContext.Request.Cookies[_options.Cookie.Name];
4646

4747
// We want to delay reading the form as much as possible, for example in case of large file uploads,
4848
// request token could be part of the header.
@@ -69,22 +69,12 @@ public void SaveCookieToken(HttpContext httpContext, string token)
6969
Debug.Assert(httpContext != null);
7070
Debug.Assert(token != null);
7171

72-
var options = new CookieOptions
73-
{
74-
HttpOnly = true,
75-
#pragma warning disable 618
76-
Domain = _options.CookieDomain,
77-
#pragma warning restore 618
78-
SameSite = SameSiteMode.Strict,
79-
Secure = _options.RequireSsl
80-
};
81-
82-
#pragma warning disable 618
83-
if (_options.CookiePath != null)
72+
var options = _options.Cookie.Build(httpContext);
73+
74+
if (_options.Cookie.Path != null)
8475
{
85-
options.Path = _options.CookiePath.ToString();
76+
options.Path = _options.Cookie.Path.ToString();
8677
}
87-
#pragma warning restore 618
8878
else
8979
{
9080
var pathBase = httpContext.Request.PathBase.ToString();
@@ -94,9 +84,7 @@ public void SaveCookieToken(HttpContext httpContext, string token)
9484
}
9585
}
9686

97-
_options.ConfigureCookieOptions?.Invoke(httpContext, options);
98-
99-
httpContext.Response.Cookies.Append(_options.CookieName, token, options);
87+
httpContext.Response.Cookies.Append(_options.Cookie.Name, token, options);
10088
}
10189
}
10290
}

0 commit comments

Comments
 (0)