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

AntiForgery Interfaces. #180

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from 6 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
97 changes: 97 additions & 0 deletions src/Microsoft.AspNet.Mvc.Core/AntiForgery/AntiForgery.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
using System.ComponentModel;
using System.Threading.Tasks;
using Microsoft.AspNet.Abstractions;
using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Security.DataProtection;

namespace Microsoft.AspNet.Mvc
{
/// <summary>
/// Provides access to the anti-forgery system, which provides protection against
/// Cross-site Request Forgery (XSRF, also called CSRF) attacks.
/// </summary>
public sealed class AntiForgery
{
private static readonly string _purpose = "Microsoft.AspNet.Mvc.AntiXsrf.AntiForgeryToken.v1";
private readonly AntiForgeryWorker _worker;

public AntiForgery([NotNull] IClaimUidExtractor claimUidExtractor,
[NotNull] IDataProtectionProvider dataProtectionProvider,
[NotNull] IAntiForgeryAdditionalDataProvider additionalDataProvider)
{
// TODO: This is temporary till we figure out how to flow configs using DI.
var config = new AntiForgeryConfigWrapper();
var serializer = new AntiForgeryTokenSerializer(dataProtectionProvider.CreateProtector(_purpose));
var tokenStore = new AntiForgeryTokenStore(config, serializer);
var tokenProvider = new TokenProvider(config, claimUidExtractor, additionalDataProvider);
_worker = new AntiForgeryWorker(serializer, config, tokenStore, tokenProvider, tokenProvider);
}

/// <summary>
/// Generates an anti-forgery token for this request. This token can
/// be validated by calling the Validate() method.
/// </summary>
/// <param name="context">The HTTP context associated with the current call.</param>
/// <returns>An HTML string corresponding to an &lt;input type="hidden"&gt;
/// element. This element should be put inside a &lt;form&gt;.</returns>
/// <remarks>
/// This method has a side effect: A response cookie is set if there is no valid cookie associated with the request.
Copy link
Contributor

Choose a reason for hiding this comment

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

line length.

Generally if there is a scroll bar when you set up the PR, I'm going to go and comment on it.

/// </remarks>
public HtmlString GetHtml([NotNull] HttpContext context)
{
TagBuilder builder = _worker.GetFormInputElement(context);
return builder.ToHtmlString(TagRenderMode.SelfClosing);
}

/// <summary>
/// Generates an anti-forgery token pair (cookie and form token) for this request.
/// This method is similar to GetHtml(HttpContext context), but this method gives the caller control
/// over how to persist the returned values. To validate these tokens, call the
/// appropriate overload of Validate.
/// </summary>
/// <param name="context">The HTTP context associated with the current call.</param>
/// <param name="oldCookieToken">The anti-forgery token - if any - that already existed
/// for this request. May be null. The anti-forgery system will try to reuse this cookie
/// value when generating a matching form token.</param>
/// <remarks>
/// Unlike the GetHtml(HttpContext context) method, this method has no side effect. The caller
/// is responsible for setting the response cookie and injecting the returned
/// form token as appropriate.
/// </remarks>
Copy link
Contributor

Choose a reason for hiding this comment

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

where is the opening of the tag

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for catching that!

public AntiForgeryTokenSet GetTokens([NotNull] HttpContext context, string oldCookieToken)
{
// Will contain a new cookie value if the old cookie token
// was null or invalid. If this value is non-null when the method completes, the caller
// must persist this value in the form of a response cookie, and the existing cookie value
// should be discarded. If this value is null when the method completes, the existing
// cookie value was valid and needn't be modified.
return _worker.GetTokens(context, oldCookieToken);
}

/// <summary>
/// Validates an anti-forgery token that was supplied for this request.
/// The anti-forgery token may be generated by calling GetHtml(HttpContext context).
/// </summary>
/// <param name="context">The HTTP context associated with the current call.</param>
public async Task ValidateAsync([NotNull] HttpContext context)
{
await _worker.ValidateAsync(context);
}

/// <summary>
/// Validates an anti-forgery token pair that was generated by the GetTokens method.
/// </summary>
/// <param name="context">The HTTP context associated with the current call.</param>
/// <param name="cookieToken">The token that was supplied in the request cookie.</param>
/// <param name="formToken">The token that was supplied in the request form body.</param>
public void Validate([NotNull] HttpContext context, string cookieToken, string formToken)
{
_worker.Validate(context, cookieToken, formToken);
}

public void Validate([NotNull] HttpContext context, AntiForgeryTokenSet antiForgeryTokenSet)
{
Validate(context, antiForgeryTokenSet.CookieToken, antiForgeryTokenSet.FormToken);
}
}
}
64 changes: 64 additions & 0 deletions src/Microsoft.AspNet.Mvc.Core/AntiForgery/AntiForgeryConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
namespace Microsoft.AspNet.Mvc
{
/// <summary>
/// Provides programmatic configuration for the anti-forgery token system.
/// </summary>
public static class AntiForgeryConfig
Copy link
Contributor

Choose a reason for hiding this comment

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

Like above, seems like this should be a non-static type injected into the DI

Copy link
Contributor

Choose a reason for hiding this comment

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

@harshgMSFT what is the conclusion on this comment? We don't have any static configs anywhere in the WebFX system

Copy link
Contributor

Choose a reason for hiding this comment

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

I see that the wrapper takes care of it, it's still kind off funky. @lodejard, @davidfowl thoughts?

{
internal const string AntiForgeryTokenFieldName = "__RequestVerificationToken";
private static string _cookieName;

/// <summary>
/// Specifies the name of the cookie that is used by the anti-forgery
/// system.
/// </summary>
/// <remarks>
/// If an explicit name is not provided, the system will automatically
/// generate a name.
/// </remarks>
public static string CookieName
{
get
{
if (_cookieName == null)
{
_cookieName = GetAntiForgeryCookieName();
}
return _cookieName;
}
set
{
_cookieName = value;
}
}

/// <summary>
/// Specifies whether SSL is required for the anti-forgery system
/// to operate. If this setting is 'true' and a non-SSL request
/// comes into the system, all anti-forgery APIs will fail.
/// </summary>
public static 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 static bool SuppressXFrameOptionsHeader
{
get;
set;
}

// TODO: Replace the stub.
private static string GetAntiForgeryCookieName()
{
return AntiForgeryTokenFieldName;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
namespace Microsoft.AspNet.Mvc
{
public sealed class AntiForgeryConfigWrapper : IAntiForgeryConfig
{
public string CookieName
{
get { return AntiForgeryConfig.CookieName; }
}

public string FormFieldName
{
get { return AntiForgeryConfig.AntiForgeryTokenFieldName; }
}

public bool RequireSSL
{
get { return AntiForgeryConfig.RequireSsl; }
}

public bool SuppressXFrameOptionsHeader
{
get { return AntiForgeryConfig.SuppressXFrameOptionsHeader; }
}
}
}
52 changes: 52 additions & 0 deletions src/Microsoft.AspNet.Mvc.Core/AntiForgery/AntiForgeryToken.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using System;

namespace Microsoft.AspNet.Mvc
{
internal sealed class AntiForgeryToken
{
internal const int SecurityTokenBitLength = 128;
internal const int ClaimUidBitLength = 256;

private string _additionalData = string.Empty;
private string _username = string.Empty;
private BinaryBlob _securityToken;

public string AdditionalData
{
get { return _additionalData; }
set
{
_additionalData = value ?? string.Empty;
}
}

public BinaryBlob ClaimUid { get; set; }

public bool IsSessionToken { get; set; }

public BinaryBlob SecurityToken
{
get
{
if (_securityToken == null)
{
_securityToken = new BinaryBlob(SecurityTokenBitLength);
}
return _securityToken;
}
set
{
_securityToken = value;
}
}

public string Username
{
get { return _username; }
set
{
_username = value ?? string.Empty;
}
}
}
}
Loading