Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set the AntiForgeryToken cookie path

The former HtmlHelper.AntiForgeryToken method which allows one to override the string path is deprecated.

[ObsoleteAttribute("This method is deprecated. Use the AntiForgeryToken() method instead. To specify a custom domain for the generated cookie, use the <httpCookies> configuration element. To specify custom data to be embedded within the token, use the static AntiForgeryConfig.AdditionalDataProvider property.", 
    true)]
public MvcHtmlString AntiForgeryToken(
    string salt,
    string domain,
    string path
)

Tells you to use <httpCookies>. BUT httpCookies Element does not have a setting for PATH.

Is this an oversight in the deprecation of this method? What is the best way to overwrite this cookie path? (manually?) Running website in a virtual application is not implicitly adding the application path to the __RequestVeririfcation cookie.

like image 811
felickz Avatar asked Nov 12 '15 18:11

felickz


People also ask

What does HTML AntiForgeryToken () do?

AntiForgeryToken()Generates a hidden form field (anti-forgery token) that is validated when the form is submitted.

How do you fix Anti-forgery cookies?

Try quick fixes The common “possible solutions” to anti-forgery token/cookie related issues are disabling output caching and enabling heuristic checks.

What is AntiForgeryToken in asp net core?

In ASP.NET Core, @Html. AntiForgeryToken() is applied for preventing cross-site request forgery (XSRF/CSRF) attacks.

What is __ Requestverificationtoken cookie?

__RequestVerificationToken Session www.ese-hormones.org Strictly Necessary This is an anti-forgery cookie set by web applications built using ASP.NET MVC technologies. It is designed to stop unauthorized posting of content to the website, known as Cross-Site Request Forgery.


3 Answers

Looking at the deprecation message:

"This method is deprecated. Use the AntiForgeryToken() method instead. To specify a custom domain for the generated cookie, use the configuration element. To specify custom data to be embedded within the token, use the static AntiForgeryConfig.AdditionalDataProvider property."

It tells us we can validate additional parameters whenever the forgery token is read back. So even if we can't set the path in the cookie, we can set the path as a property inside the token. To validate it later on, for example:

public class AdditionalDataProvider : IAntiForgeryAdditionalDataProvider
{
    public string GetAdditionalData(HttpContextBase context)
    {
        return AdditionalData(context);
    }

    public bool ValidateAdditionalData(HttpContextBase context, string additionalData)
    {
        var currentData = AdditionalData(context);
        return currentData == additionalData;
    }

    private static string AdditionalData(HttpContextBase context)
    {
        var path = context.Request.ApplicationPath;
        return path;
    }
}

When asp.net generates the token it will store the current path (or any other unique value you want to validate) for that app and if you have another app running on a different path, when the token gets sent to that app (due to the lack of cookie path) it will validate the previous app properties against that app's properties. If it is a different set of properties it will fail and deny the request.

Additionally, looking at the code for the AntiforgeryConfig.cs, if the app is running in a virtual directory, it will add that virtual directory in the cookie's name by default:

private static string GetAntiForgeryCookieName()
{
    return GetAntiForgeryCookieName(HttpRuntime.AppDomainAppVirtualPath);
}

// If the app path is provided, we're generating a cookie name rather than a field name, and the cookie names should
// be unique so that a development server cookie and an IIS cookie - both running on localhost - don't stomp on
// each other.
internal static string GetAntiForgeryCookieName(string appPath)
{
    if (String.IsNullOrEmpty(appPath) || appPath == "/")
    {
        return AntiForgeryTokenFieldName;
    }
    else
    {
        return AntiForgeryTokenFieldName + "_" + HttpServerUtility.UrlTokenEncode(Encoding.UTF8.GetBytes(appPath));
    }
}

So it will be like this: _RequestVerificationToken vs _RequestVerificationToken_L2RIdjAz0

Meaning App2 although can receive tokens from App1, it won't be able to read them since it will be looking always for App2 verification token only.

HTH

like image 186
amd989 Avatar answered Oct 09 '22 17:10

amd989


For ASP.NET Core - See: AntiforgeryOptions Class

Cookie - Determines the settings used to create the antiforgery cookies.

Ex (adapted from Prevent Cross-Site Request Forgery (XSRF/CSRF) attacks in ASP.NET Core):

services.AddAntiforgery(options => 
{
    options.Cookie.Path = "Path";
});
like image 43
felickz Avatar answered Oct 09 '22 17:10

felickz


The best aproach to overwrite AntiForgeryToken's cookie configuration (Path, HttpOnly,...) is with encapsulation (Microsoft team post).

It is possible to configure the cookie path instead of setting it on the properties.

public static class AntiForgeryTokenExtensions
{
    ///<summary>
    ///Generates a hidden form field (anti-forgery token) that is 
    ///validated when the form is submitted. Furthermore, this extension 
    ///applies custom settings on the generated cookie. 
    ///</summary>
    ///<returns>Generated form field (anti-forgery token).</returns>
    public static MvcHtmlString AntiForgeryTokenExtension(this HtmlHelper html)
    {
        // Call base AntiForgeryToken and save its output to return later.
        var output = html.AntiForgeryToken();
        
        // Check that cookie exists
        if(HttpContext.Current.Response.Cookies.AllKeys.Contains(AntiForgeryConfig.CookieName))
        {
            // Set cookie into the variable
            var antiForgeryTokenCookie = HttpContext.Current.Response.Cookies.Get(AntiForgeryConfig.CookieName);
            
            // Set cookie configuration
            antiForgeryTokenCookie.Path = "/Path";
            // antiForgeryTokenCookie.HttpOnly = true;
            // ...
        }
        
        return output;
    }
}

There is a last change that must be done and it is replace AntiForgeryToken() for AntiForgeryTokenExtension() if it is an existing project.

NOTES

  • With this code you can configure AntiForgeryToken cookie as a normal cookie.
  • It is also possible to add input parameters to this method, but I am not sure it would be a good practice.
  • There are different ways to get the cookies but I think that through Response.Cookies is the "most correct", since it is a response cookie.

IMPORTANT

It is needed to check if cookie exist first before trying to get it. If you try to get a Response cookie which doesn't exist, it will be generated. It doesn't happen with Request cookies.

COOKIE KNOWLEDGE

It is not the question itself but explains part of the code and it is quite important to know when we are working with cookies, so I consider it is good to have this information here too.

  • All Response.Cookies are in Request.Cookies, but not all Request.Cookies are in Response.Cookies.

  • If you create a Response.Cookie it will appear also in Request.Cookies.

  • If you create a Request.Cookie it will NOT appear in Response.Cookies.

  • If you try to get a non-existent cookie from Request.Cookies it will return a null.

  • If you try to get a non-existent cookie Response.Cookies it will return a new generated cookie.

SOURCES

There is the link where the developers tell to use encapsulation and many other things that could be useful. Microsoft developers recommendations and information

Source to knowledge of cookies, Request.Cookies and Response.Cookies differences.

Difference between request cookies and response cookies

Difference between request cookies and response cookies 2

Check if cookie exist and difference between kind of cookies

like image 45
Dailosrs Avatar answered Oct 09 '22 15:10

Dailosrs