-
Notifications
You must be signed in to change notification settings - Fork 2.1k
AntiForgery Interfaces. #180
Changes from 6 commits
314b0d8
3895dc2
fb44694
2b0d472
c143153
20fdbe2
08a1c50
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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 <input type="hidden"> | ||
/// element. This element should be put inside a <form>.</returns> | ||
/// <remarks> | ||
/// This method has a side effect: A response cookie is set if there is no valid cookie associated with the request. | ||
/// </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> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. where is the opening of the tag There was a problem hiding this comment. Choose a reason for hiding this commentThe 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); | ||
} | ||
} | ||
} |
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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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; } | ||
} | ||
} | ||
} |
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; | ||
} | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
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.