Skip to content
This repository was archived by the owner on Nov 22, 2018. It is now read-only.
Merged
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
145 changes: 83 additions & 62 deletions src/Microsoft.AspNetCore.Antiforgery/AntiforgeryOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,102 +14,123 @@ public class AntiforgeryOptions
private const string AntiforgeryTokenFieldName = "__RequestVerificationToken";
private const string AntiforgeryTokenHeaderName = "RequestVerificationToken";

private string _cookieName;
private string _formFieldName = AntiforgeryTokenFieldName;

private CookieBuilder _cookieBuilder = new CookieBuilder
{
SameSite = SameSiteMode.Strict,
HttpOnly = true
};

/// <summary>
/// The default cookie prefix, which is ".AspNetCore.Antiforgery.".
/// </summary>
public static readonly string DefaultCookiePrefix = ".AspNetCore.Antiforgery.";

/// <summary>
/// Specifies the name of the cookie that is used by the antiforgery system.
/// Determines the settings used to create the antiforgery cookies.
/// </summary>
/// <remarks>
/// If an explicit name is not provided, the system will automatically generate a
/// <para>
/// If an explicit <see cref="CookieBuilder.Name"/> is not provided, the system will automatically generate a
/// unique name that begins with <see cref="DefaultCookiePrefix"/>.
/// </para>
/// <para>
/// <see cref="CookieBuilder.SameSite"/> defaults to <see cref="SameSiteMode.Strict"/>.
/// <see cref="CookieBuilder.HttpOnly"/> defaults to <c>true</c>.
/// </para>
/// </remarks>
public string CookieName
public CookieBuilder Cookie
{
get
{
return _cookieName;
}
set
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}

_cookieName = value;
}
get => _cookieBuilder;
set => _cookieBuilder = value ?? throw new ArgumentNullException(nameof(value));
}

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

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

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

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

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

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


/// <summary>
/// <para>
/// This property is obsolete and will be removed in a future version.
/// The recommended alternative is to set <seealso cref="CookieBuilder.SecurePolicy"/> on <see cref="Cookie"/>.
/// </para>
/// <para>
/// <c>true</c> is equivalent to <see cref="CookieSecurePolicy.Always"/>.
/// <c>false</c> is equivalent to <see cref="CookieSecurePolicy.None"/>.
/// </para>
/// <para>
/// Specifies whether SSL is required for the antiforgery system
/// to operate. If this setting is 'true' and a non-SSL request
/// comes into the system, all antiforgery APIs will fail.
/// </para>
/// </summary>
public bool RequireSsl { get; set; }

/// <summary>
/// Specifies whether to suppress the generation of X-Frame-Options header
/// which is used to prevent ClickJacking. By default, the X-Frame-Options
/// header is generated with the value SAMEORIGIN. If this setting is 'true',
/// the X-Frame-Options header will not be generated for the response.
/// </summary>
public bool SuppressXFrameOptionsHeader { get; set; }
[Obsolete("This property is obsolete and will be removed in a future version. The recommended alternative is to set " + nameof(Cookie) + "." + nameof(CookieBuilder.SecurePolicy) + ".")]
public bool RequireSsl
{
get => Cookie.SecurePolicy == CookieSecurePolicy.Always;
set => Cookie.SecurePolicy = value ? CookieSecurePolicy.Always : CookieSecurePolicy.None;
}
#endregion
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ public AntiforgeryOptionsSetup(IOptions<DataProtectionOptions> dataProtectionOpt

public static void ConfigureOptions(AntiforgeryOptions options, DataProtectionOptions dataProtectionOptions)
{
if (options.CookieName == null)
if (options.Cookie.Name == null)
{
var applicationId = dataProtectionOptions.ApplicationDiscriminator ?? string.Empty;
options.CookieName = AntiforgeryOptions.DefaultCookiePrefix + ComputeCookieName(applicationId);
options.Cookie.Name = AntiforgeryOptions.DefaultCookiePrefix + ComputeCookieName(applicationId);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public async Task<bool> IsRequestValidAsync(HttpContext httpContext)
var tokens = await _tokenStore.GetRequestTokensAsync(httpContext);
if (tokens.CookieToken == null)
{
_logger.MissingCookieToken(_options.CookieName);
_logger.MissingCookieToken(_options.Cookie.Name);
return false;
}

Expand Down Expand Up @@ -160,7 +160,7 @@ public async Task ValidateRequestAsync(HttpContext httpContext)
if (tokens.CookieToken == null)
{
throw new AntiforgeryValidationException(
Resources.FormatAntiforgery_CookieToken_MustBeProvided(_options.CookieName));
Resources.FormatAntiforgery_CookieToken_MustBeProvided(_options.Cookie.Name));
}

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

private void CheckSSLConfig(HttpContext context)
{
if (_options.RequireSsl && !context.Request.IsHttps)
if (_options.Cookie.SecurePolicy == CookieSecurePolicy.Always && !context.Request.IsHttps)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok cool 👍

{
throw new InvalidOperationException(Resources.FormatAntiforgeryWorker_RequireSSL(
nameof(AntiforgeryOptions),
nameof(AntiforgeryOptions.RequireSsl),
"true"));
throw new InvalidOperationException(Resources.FormatAntiforgery_RequiresSSL(
string.Join(".", nameof(AntiforgeryOptions), nameof(AntiforgeryOptions.Cookie), nameof(CookieBuilder.SecurePolicy)),
nameof(CookieSecurePolicy.Always)));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public string GetCookieToken(HttpContext httpContext)
{
Debug.Assert(httpContext != null);

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

var cookieToken = httpContext.Request.Cookies[_options.CookieName];
var cookieToken = httpContext.Request.Cookies[_options.Cookie.Name];

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

var options = new CookieOptions
{
HttpOnly = true,
#pragma warning disable 618
Domain = _options.CookieDomain,
#pragma warning restore 618
SameSite = SameSiteMode.Strict,
Secure = _options.RequireSsl
};

#pragma warning disable 618
if (_options.CookiePath != null)
var options = _options.Cookie.Build(httpContext);

if (_options.Cookie.Path != null)
{
options.Path = _options.CookiePath.ToString();
options.Path = _options.Cookie.Path.ToString();
}
#pragma warning restore 618
else
{
var pathBase = httpContext.Request.PathBase.ToString();
Expand All @@ -94,9 +84,7 @@ public void SaveCookieToken(HttpContext httpContext, string token)
}
}

_options.ConfigureCookieOptions?.Invoke(httpContext, options);

httpContext.Response.Cookies.Append(_options.CookieName, token, options);
httpContext.Response.Cookies.Append(_options.Cookie.Name, token, options);
}
}
}
Loading