C
C#•2y ago
joy

anti forgery token asp global asax file

hi all, currently i try to implement the anti forgery token following microsoft article (the csrf and ajax section). https://learn.microsoft.com/en-us/aspnet/web-api/overview/security/preventing-cross-site-request-forgery-csrf-attacks so if i make a post request to my form, the anti forgery token will be send from my javascript file to asp controller. here's the implementation i did :
public class CustomAntiForgery : FilterAttribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}

var httpContext = filterContext.HttpContext;
var cookie = httpContext.Request.Cookies[AntiForgeryConfig.CookieName];
AntiForgery.Validate(cookie != null ? cookie.Value : null, httpContext.Request.Headers["__RequestVerificationToken"]);
}
}
public class CustomAntiForgery : FilterAttribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}

var httpContext = filterContext.HttpContext;
var cookie = httpContext.Request.Cookies[AntiForgeryConfig.CookieName];
AntiForgery.Validate(cookie != null ? cookie.Value : null, httpContext.Request.Headers["__RequestVerificationToken"]);
}
}
my controller :
[HttpPost]
[CustomAntiForgery]
public ActionResult AddMemo{ //...}
[HttpPost]
[CustomAntiForgery]
public ActionResult AddMemo{ //...}
to enable the anti csrf token by default in global asax file, do we need to add CustomAntiForgery into the Application_Start() method? so it looks like this
[CustomAntiForgery]
protected void Application_Start()
{ //... }
[CustomAntiForgery]
protected void Application_Start()
{ //... }
14 Replies
Brady Kelly
Brady Kelly•2y ago
Why are you using a custom anti-forgery? What is wrong with the existing ValidateAntiForgeryToken filter?
joy
joy•2y ago
because previously i followed an answer from stackoverflow on the CustomAntiForgery but i try to debug and it works so i think it's okay, when i try to pass different token and a correct token, the method validate it. but do we need to add it on the Application_Start() so its enabled by default? 🤔
Brady Kelly
Brady Kelly•2y ago
You can't just validate for all requests because not all will include the token. It is recommended to use this:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
});
}
}
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
});
}
}
Then on actions where you may want to ignore it you can use the IgnoreAntiforgeryToken attribute
joy
joy•2y ago
yeah, i found the one for net core.. but in net framework only have global.asax.cs file so I'm wondering if its correct to add the attribute above application_start method
Brady Kelly
Brady Kelly•2y ago
Oh, sorry, I haven't used this in ages so had to look up an example but it's like this:
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
}
}

// FilterConfig.cs located in App_Start folder
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
}
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
}
}

// FilterConfig.cs located in App_Start folder
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
}
joy
joy•2y ago
ohh.. so we will need to add it inside FilterConfig class, instead of adding them as a attribute..
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
filters.Add(new CustomAntiForgery());
}
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
filters.Add(new CustomAntiForgery());
}
it looks like this.. i'll try this out.. thanks!! i think because it's set globally so i got this error " The required anti-forgery form field "__RequestVerificationToken" is not present." , i think i'll need to use the IgnoreAntiForgery token?
Brady Kelly
Brady Kelly•2y ago
Oh shit, sorry, I made a mistake with my copy/paste. I was thinking of the AutoIgnoreAntiforgeryToken but that's only in Core. This is happening because not all requests carry the token. Your custom attribute will need to check for this. Be right back.
joy
joy•2y ago
ohh so this one is not working in asp framework, is that right? 🤔
Brady Kelly
Brady Kelly•2y ago
Have a look at this blog post (https://weblogs.asp.net/dixin/anti-forgery-request-recipes-for-asp-net-mvc-and-ajax) where they use a ValidateAntiForgeryTokenWrapperAttribute which would be similar to your CustomAntiForgery but it takes HttpVerbs verbs in the ctor so you can tell it to only validate post requests. You should be able to do that in filters.Add(new CustomAntiForgery(HttpVerbs.Post)). Ignore the salt parameter mentioned in the blog as that is deprecated.
Brady Kelly
Brady Kelly•2y ago
Something like this:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method,
AllowMultiple = false, Inherited = true)]
public class ValidateAntiForgeryTokenWrapperAttribute : FilterAttribute, IAuthorizationFilter
{
private readonly ValidateAntiForgeryTokenAttribute _validator;

private readonly AcceptVerbsAttribute _verbs;

public ValidateAntiForgeryTokenWrapperAttribute(HttpVerbs verbs)
: this(verbs)
{
}

public ValidateAntiForgeryTokenWrapperAttribute(HttpVerbs verbs)
{
this._verbs = new AcceptVerbsAttribute(verbs);
this._validator = new ValidateAntiForgeryTokenAttribute();
}

public void OnAuthorization(AuthorizationContext filterContext)
{
string httpMethodOverride = filterContext.HttpContext.Request.GetHttpMethodOverride();
if (this._verbs.Verbs.Contains(httpMethodOverride, StringComparer.OrdinalIgnoreCase))
{
this._validator.OnAuthorization(filterContext);
}
}
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method,
AllowMultiple = false, Inherited = true)]
public class ValidateAntiForgeryTokenWrapperAttribute : FilterAttribute, IAuthorizationFilter
{
private readonly ValidateAntiForgeryTokenAttribute _validator;

private readonly AcceptVerbsAttribute _verbs;

public ValidateAntiForgeryTokenWrapperAttribute(HttpVerbs verbs)
: this(verbs)
{
}

public ValidateAntiForgeryTokenWrapperAttribute(HttpVerbs verbs)
{
this._verbs = new AcceptVerbsAttribute(verbs);
this._validator = new ValidateAntiForgeryTokenAttribute();
}

public void OnAuthorization(AuthorizationContext filterContext)
{
string httpMethodOverride = filterContext.HttpContext.Request.GetHttpMethodOverride();
if (this._verbs.Verbs.Contains(httpMethodOverride, StringComparer.OrdinalIgnoreCase))
{
this._validator.OnAuthorization(filterContext);
}
}
}
Notice how the wrapper class checks the verbs passed and uses the existing attribute class to do the validation, and because you only pass POST it won't try and validate for GET requests and that should sort out the error you are getting.
joy
joy•2y ago
hmm.. i'll try this out..
Brady Kelly
Brady Kelly•2y ago
I hope we can make this work otherwise I've messed you around. BTW, just why are you still using .NET Framework?
joy
joy•2y ago
yup i think there'll be lots of changes, it might take a while to see the result. actually it's an ongoing project (also lots of codes) so migrating to net core will also take time and for now decided to just keep it first but if i create a new project, i use asp net core instead..
Brady Kelly
Brady Kelly•2y ago
Cool
Want results from more Discord servers?
Add your server
More Posts