Coder Social home page Coder Social logo

aspnet / antiforgery Goto Github PK

View Code? Open in Web Editor NEW
78.0 50.0 41.0 624 KB

[Archived] AntiForgery token feature for ASP.NET Core. Project moved to https://github.com/aspnet/AspNetCore

License: Apache License 2.0

Batchfile 0.22% Shell 3.94% C# 93.01% PowerShell 2.83%
aspnet-product

antiforgery's People

Contributors

ajaybhargavb avatar aspnetci avatar brennanconroy avatar chris2093 avatar ciwchris avatar davidfowl avatar dougbu avatar eilon avatar haok avatar hishamco avatar javiercn avatar jkotalik avatar jnaputi253 avatar juntaoluo avatar kichalla avatar mikeharder avatar mkartakmsft avatar natemcmaster avatar ntaylormullen avatar pakrym avatar pranavkm avatar ryanbrandenburg avatar rynowak avatar smitpatel avatar tratcher avatar troydai avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

antiforgery's Issues

Question: `no-store` versus `no-cache` for Antiforgery

This question is related to how caching and Antiforgery was handled for #105.

Looking at

// Explicitly set the cache headers to 'no-cache'. This could override any user set value but this is fine
// as a response with antiforgery token must never be cached.
SetDoNotCacheHeaders(httpContext);
...

Explicitly set the cache headers to 'no-cache'. This could override any user set value but this is fine as a response with antiforgery token must never be cached.

and thus SetDoNotCacheHeaders() ...

private void SetDoNotCacheHeaders(HttpContext httpContext)
{
// Since antifogery token generation is not very obvious to the end users (ex: MVC's form tag generates them
// by default), log a warning to let users know of the change in behavior to any cache headers they might
// have set explicitly.
LogCacheHeaderOverrideWarning(httpContext.Response);
httpContext.Response.Headers[HeaderNames.CacheControl] = "no-cache";
httpContext.Response.Headers[HeaderNames.Pragma] = "no-cache";
}

@JunTaoLuo said ref ...

The proposal is to disable caching when antiforgery is used regardless of whether cookies are being set.

RFC 7234 doesn't guarantee that storage will not occur tho ...

5.2.1.4. no-cache
The "no-cache" request directive indicates that a cache MUST NOT use a stored response to satisfy the request without successful validation on the origin server.

Wondering: Why doesn't Antiforgery set no-store rather than no-cache?

DefaultAntiforgery.SaveCookieTokenAndHeader should not override stricter X-Frame-Options headers

Currently, SaveCookieTokenAndHeader always replaces the X-Frame-Options header with its own value, even if a stricter header has already been added to the response headers by another middleware (e.g NWebsec).

Of course, SuppressXFrameOptionsHeader could be used to prevent SaveCookieTokenAndHeader from updating the X-Frame-Options header but I believe it would be better to add a check to avoid overriding it in this case, specially if the existing header is stricter (i.e uses DENY).

/cc @blowdart

AntiForgeryToken is broken - Server cannot append header after HTTP headers have been sent.

I am implementing AntiForgeryToken my login form.

When I run project, its call Account/Login Get mothod and return view() i.e login.cshtml

In login.cshtml view page, I have

@using (Html.BeginForm("Login", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { @class = "form1" }))
{
    @Html.AntiForgeryToken(); // throw exception 
    <label class="username_style" for="UserName"></label>
    @Html.TextBoxFor(m => m.UserName, new { placeholder = "UserName", autofocus = true })

    <label class="password_style" for="Password"></label>
    @Html.TextBoxFor(m => m.Password, new { type = "password", placeholder = "Password" })

    <p class="msg error">@Html.ValidationSummary(false, "", new { @class = "msg error" })</p>
    <input type="submit" name="login" value="Login" id="btnLogin" />
    <p><a href="javascript:void(0)" class="elink">Forgot Password?</a></p>
}

When server return login.cshtml page I got this exception

I am implementing AntiForgeryToken my login form.

When I run project, its call Account/Login Get mothod and return view() i.e login.cshtml

In login.cshtml view page, I have

@using (Html.BeginForm("Login", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { @class = "form1" }))
{
    @Html.AntiForgeryToken(); // throw exception 
    <label class="username_style" for="UserName"></label>
    @Html.TextBoxFor(m => m.UserName, new { placeholder = "UserName", autofocus = true })

    <label class="password_style" for="Password"></label>
    @Html.TextBoxFor(m => m.Password, new { type = "password", placeholder = "Password" })

    <p class="msg error">@Html.ValidationSummary(false, "", new { @class = "msg error" })</p>
    <input type="submit" name="login" value="Login" id="btnLogin" />
    <p><a href="javascript:void(0)" class="elink">Forgot Password?</a></p>
}

When server return login.cshtml page

Server cannot append header after HTTP headers have been sent.

I can not figure out how to solve this error.

Thank you,

Cookie path is always / in IIS

When you put your application to virtual directory named myvirtualpath in IIS, antiforgery cookie is still using / as path and not /myvirtualpath.

Cookie header request example

I looked at the AntiforgerySample but I'm still confused how this works in an Angular SPA environment (where the majority of [ValidateAntiforgeryToken] is declared on the backend WebApi in my project).
I have followed the same as the sample, but I will also note I have added Identity, which I think also adds the Antiforgery service for itself(?).

I have done a login page and a logoff page, where the cshtmls are 'dumb' and I have HttpPost methods LogIn and LogOff [ValidateAntiforgeryToken] as WebApi methods that the angular controller calls.
The first time it generates the token and I can successfully log on in the Login page.
However, any subsequent WebApi calls that have [ValidateAntiforgeryToken] (eg. my LogOff WebApi method), I keep getting The provided antiforgery token was meant for a different claims-based user than the current user.
Looking at Fiddler, I see 3 cookie tokens sent on request (each with different values):
.AspNetCore.Antiforgery.xxxx
.AspNetCore.Identity.Application
XSRF-TOKEN

Am I missing something in my case? Do I need to override how the validation is working?

Provide appropriate error message in case of missing antiforgery tokens

Moved from: aspnet/Mvc#1210

Scenario as mentioned in below article:
http://www.asp.net/web-api/overview/security/preventing-cross-site-request-forgery-(csrf)-attacks

The error message says The required anti-forgery cookie "__RequestVerificationToken" is not present...notice that it mentions the form field name here...

services.AddSingleton<CustomAntiForgeryTokenFilter>();

//---------------------------------

public class CustomAntiForgeryTokenFilter : IAuthorizationFilter
{
    private readonly AntiForgery _antiForgery;

    public CustomAntiForgeryTokenFilter(AntiForgery antiForgery)
    {
        _antiForgery = antiForgery;
    }

    public void OnAuthorization(AuthorizationContext context)
    {
        string cookieToken = string.Empty;
        string formToken = string.Empty;

        string[] tokenHeaders;
        if (context.HttpContext.Request.Headers.TryGetValue("RequestVerificationToken", out tokenHeaders))
        {
            string[] tokens = tokenHeaders[0].Split(':');
            cookieToken = tokens[0].Trim();
            formToken = tokens[1].Trim();
        }

        _antiForgery.Validate(context.HttpContext, cookieToken, formToken);
    }
}

//---------------------------------

[ServiceFilter(typeof(CustomAntiForgeryTokenFilter), Order = 1)]
[Authorize(Order = 2)]
public class ValuesController : Controller
{
    [HttpPost("api/values")]
    public Person Create([FromBody]Person data)
    {

        return data;
    }
}

Error Message

System.InvalidOperationException: The required anti-forgery cookie "__RequestVerificationToken" is not present.
at Microsoft.AspNet.Mvc.TokenProvider.ValidateTokens(HttpContext httpContext, ClaimsIdentity identity, AntiForgeryToken sessionToken, AntiForgeryToken fieldToken)
at Microsoft.AspNet.Mvc.AntiForgeryWorker.Validate(HttpContext httpContext, String cookieToken, String formToken)
at Microsoft.AspNet.Mvc.AntiForgery.Validate(HttpContext context, String cookieToken, String formToken)
at WebApplication10.CustomAntiForgeryTokenFilter.OnAuthorizationAsync(AuthorizationContext context) in C:\Users\kichalla\Documents\Visual Studio 14\Projects\WebApplication10\src\WebApplication10\CustomAntiForgeryTokenFilterAttribute.cs:line 33
at Microsoft.AspNet.Mvc.FilterActionInvoker.<InvokeAuthorizationFilter>d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNet.Mvc.FilterActionInvoker.<InvokeActionAuthorizationFilters>d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNet.Mvc.FilterActionInvoker.<InvokeExceptionFilter>d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNet.Mvc.FilterActionInvoker.<InvokeAsync>d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNet.Mvc.ReflectedActionInvoker.<InvokeAsync>d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
at Microsoft.AspNet.Mvc.MvcRouteHandler.<RouteAsync>d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNet.Routing.Template.TemplateRoute.<RouteAsync>d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNet.Mvc.Routing.AttributeRoute.<RouteAsync>d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNet.Routing.RouteCollection.<RouteAsync>d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNet.Builder.RouterMiddleware.<Invoke>d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNet.Security.Infrastructure.AuthenticationMiddleware`1.<Invoke>d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNet.Security.Infrastructure.AuthenticationMiddleware`1.<Invoke>d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNet.Security.Infrastructure.AuthenticationMiddleware`1.<Invoke>d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNet.Security.Infrastructure.AuthenticationMiddleware`1.<Invoke>d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNet.RequestContainer.ContainerMiddleware.<Invoke>d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNet.Loader.IIS.KlrHttpApplication.<ProcessRequestAsyncImpl>d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNet.Loader.IIS.HttpApplicationBase.<InvokeProcessRequestAsyncImpl>d__1.MoveNext()

Cookies "secure" flag: AntiforgeryOptions.RequiresSsl and HttpRequest.IsSecure

On the DefaultAntiforgeryTokenStore the AntiforgeryOptions.RequiresSsl flag is used to configure the "secure" flag of the resulting cookie. If AntiforgeryOptions.RequiresSsl is true, than the "secure" flag is enforced.

However, if AntiforgeryOptions.RequiresSsl is false, nothing is done on the "secure" flag. The source code contains a comment stating that the "secure" flag is populated out of band. Where's this "out of band" place exactly? Shouldn't the "secure" flag be set accordingly to HttpRequest.IsHttps, similar to how it is done on other components?

AntiforgeryOptions.RequireSsl enhancement

The current implementation enforces that if this option is enabled that the incoming request must occur over SSL. This causes an issue when you have SSL terminated on a frontend server, such as hosting a site on nginx.

The authentication system allows for the secure flag to be set regardless of the SSL state of the request. See: https://github.com/aspnet/Security/blob/dev/src/Microsoft.AspNet.Authentication.Cookies/CookieAuthenticationOptions.cs and https://github.com/aspnet/Security/blob/dev/src/Microsoft.AspNet.Authentication.Cookies/CookieSecureOption.cs. With that, using the setting of 'Always' allows the cookie to be marked secure even with SSL termination in front of aspnet.

Please consider updating the implementation to be more consistent with the authentication system, which will also support more hosting scenarios.

Thanks!

Add logging to antiforgery

We should add logging

Some ideas:

  • Validating a token (verbose)
  • Validation failure / missing token (warning)

Thinking warning is right for failures, because generally this is a app configuration issue.

Using antiforgery with AJAX requests

I'd like to request a DELETE using a button on a form wired up to ...

$.ajax({
    url: '/delete/' + resource,
    type: 'DELETE',
    async: true,
    cache: false,
    success: function(result) {
        ...
    },
    error: function(jqXHR, exception) {
        ...
    }
});

... with ...

[HttpDelete("/delete/{resource}")]
public async Task<HttpStatusCode> Delete(string resource)
{
    ...
    return HttpStatusCode.OK;
}

This works fine without ValidateAntiForgeryToken, but as soon as I go ...

[HttpDelete("/delete/{resource}"), ValidateAntiForgeryToken]

๐Ÿ’ฅ I get a 400 Bad Request.

Both the button and the script are within a <form> and I can see the antiforgery token going out on the DELETE in request headers (via Fiddler) ...

Cookie: X-XSRF-COOKIE=CfDJ8Ag6EezFPexKq5ZuFJ4kc............;

What am I missing?

`Microsoft.AspNet.Antiforgery.DefaultAntiforgery.ValidateRequestAsync` always fails

I have attempted to follow the sample source provided here. I'm currently using "Microsoft.AspNet.Antiforgery": "1.0.0-rc1-final". The sample source code seems to work "ok" but I really want something more like the current version here.

I need the ability to use the Cookie approach for my Angular2 application. How can I achieve? Here is the middleware that I'm attempting to use:

    public class AntiforgeryMiddleware
    {
        private readonly IAntiforgery _antiforgery;
        private readonly AntiforgeryOptions _options;
        private readonly RequestDelegate _next;

        public AntiforgeryMiddleware(RequestDelegate next,
                                     IAntiforgery antiforgery,
                                     IOptions<AntiforgeryOptions> options)
        {
            _next = next;
            _antiforgery = antiforgery;
            _options = options.Value;
        }

        public async Task Invoke(HttpContext context)
        {
            if (string.Equals("GET", context.Request.Method, StringComparison.OrdinalIgnoreCase))
            {
                var tokenSet = _antiforgery.GetAndStoreTokens(context);
                if (tokenSet.CookieToken != null)
                {
                    context.Response.Cookies.Append(_options.CookieName, tokenSet.CookieToken, new CookieOptions {HttpOnly = false});
                }
            }
            else if (string.Equals("POST", context.Request.Method, StringComparison.OrdinalIgnoreCase))
            {
                // At this point the context.Request.Headers has my cookie token
                // But if I were to invoke _antiforgery.GetTokens(context), it wouldn't have a cookie token!
                await _antiforgery.ValidateRequestAsync(context);
            }

            await _next(context);
        }
    }

The odd thing is that in the context.Request.Headers I have the cookie token that I'm expecting, however; the current Microsoft.AspNet.Antiforgery.DefaultAntiforgery.ValidateRequestAsync function seems to expect both a cookie and a form token -- which I believe is incorrect. Please help...

Skip anti forgery validation for non-browser clients

As I know, CSRF is only problem for browsers with cookie based authentication (since cookies are sent in a cross site request).

Think that we added global AutoValidateAntiforgeryTokenAttribute to protect out application. What if we want to use same controllers (API controllers) from a mobile application (or from postman for tests). In that case, we don't want to send antiforgery token in the cookie, because it's not a security problem for these clients, and it's hard to do it.

The problem is this code: https://github.com/aspnet/Antiforgery/blob/dev/src/Microsoft.AspNetCore.Antiforgery/Internal/DefaultAntiforgery.cs#L160

It throws exception if antiforgery cookie is not sent. My suggestion is to assume the request valid if this cookie is not present. Because, a cross-site request can not prevent to send this cookie (and just send the auth cookie).

What do you think?

How do I retrieve the antiforgery token in RC2 ?

Hi
With .NET Core RC1 the following code to validate an antiforgery token worked. I can see that the api has changed in RC2

RC1 Working code

using Microsoft.AspNet.Antiforgery;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.Filters;
using Microsoft.Extensions.OptionsModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace FortMembership.Filters
{

    public class ValidateAntiForgeryHeaderToken : TypeFilterAttribute
    {
        public ValidateAntiForgeryHeaderToken() : base(typeof(ValidateAntiForgeryHeaderTokenImpl))
        {
        }

        // see https://docs.asp.net/en/latest/mvc/controllers/filters.html
        //
        // If you have a simple filter that doesnโ€™t require any arguments, but which has constructor dependencies that need to be filled by DI, 
        // you can inherit from TypeFilterAttribute, allowing you to use your own named attribute on classes and methods (instead of [TypeFilter(typeof(FilterType))]). 
        //

        private class ValidateAntiForgeryHeaderTokenImpl : IAsyncAuthorizationFilter
        {
            private readonly IAntiforgery _antiforgery; 

            public readonly string verificationToken = "X-VerificationToken";
            public readonly string antiforgeryCookieName;

            public ValidateAntiForgeryHeaderTokenImpl(IAntiforgery antiforgery, IOptions<AntiforgeryOptions> antiforgeryOptions)
            {
                _antiforgery = antiforgery;
                antiforgeryCookieName = antiforgeryOptions.Value.CookieName; // if not specified this is autogenerated by mvc
            }

            public Task OnAuthorizationAsync(AuthorizationContext context)
            {
                string headerToken = context.HttpContext.Request.Headers[verificationToken];
                if (headerToken != null)
                {                     
                    string antiForgeryCookieValue = context.HttpContext.Request.Cookies[antiforgeryCookieName];
                    _antiforgery.ValidateTokens(context.HttpContext, new AntiforgeryTokenSet(headerToken, antiForgeryCookieValue)); // throws on invalid 
                    return Task.FromResult<object>(null);
                }
                return _antiforgery.ValidateRequestAsync(context.HttpContext);               
            }
        }
    }
}

Can you point me in the right direction with RC2 , I cannot see the API calls necessary to create a new tokenset and validate

return await _antiforgery.ValidateRequestAsync(context.HttpContext, /* new AntiforgeryTokenSet(headerToken, antiForgeryCookieValue */));

Thanks

Cookie Token is blank

Hi,
I'm using angular along with asp.net 5. I'm trying to store the cookie / form token so I can pass it into the controller on an ajax post. Everything is fine when in debug mode. When I go to the publish to IIS the cookie token is always blank.

 Constructor (IAntiforgery antiforgery)
{
}

  Method  var token = Antiforgery.GetAndStoreTokens(Context);

  token.CookieToken is blank at this point.

What am I missing here? I don't see any bugs and I'm pretty sure you have unit test on this.
I'm using Beta 7.

Configurable HttpOnly Cookie

Configurable HttpOnly Cookie

Allow API user to Configure if the cookie generated is HttpOnly or not

Functional impact

  • Allows for use of ValidationToken Facilities in Angular and other frameworks
  • Changes Hard coded true value to an optional value

Minimal repro steps

  1. Create an Angular Application and try to call endpoints secured with [ValidateToken] or [AutoValidateToken]
  2. Angular cannot find HTTPOnly cookies because of their security principals
  3. Angular does not properly send the ValidationToken HTTPHeader
    ** Example Repo: Antiforgery Demo

Expected result

Expected that because of the Architecture design, a developer using ValidateToken Configured for Angular Cookie and Header functionality, that the ValidationToken Cookie should be configured correctly.

Actual result

Angular is prevented from reading the ValidationToken Cookie because it is set as HTTPOnly, which prevents angular calling endpoints secured with [ValidateToken] or [AutoValidateToken]

Further technical details

Documentation for AngularJS V1 CSRF CookieToHeader Architecture

Wikipedia CSRF Cookie to Header which states that by the architectural design of the CookieToHeader Architecture the ValidationToken cookie needs to be readable by JavaScript

Root of issue, ellipses for brevity

namespace Microsoft.AspNetCore.Antiforgery.Internal
{
    public class DefaultAntiforgeryTokenStore : IAntiforgeryTokenStore
    {
        ...
        
        public void SaveCookieToken(HttpContext httpContext, string token)
        {
            ...
            options.HttpOnly = true; // This is hardcoded and cannot be changed
            ...
        }

        ...
    }
}

Discussion: Smarter defaults for Antiforgery

*Use this issue for feedback, questions and discussions related to aspnet/Announcements#156 *


Update 3/30

We're not 100% satisfied with what we built here, so we're not going to make any changes to the default experience for validating tokens in RC2.

We're not going to ship the AntiforgeryMiddleware because we're not confident that it's our long term approach. We're still going to be looking at a solution that works with middleware, with the authentication system and can protect more of your application than just MVC.

In MVC - the @Html.BeginForm and <form> taghelper will still generate an antiforgery token by default. The [AutoValidateAntiforgeryToken] filter will be shipped in RC2 and will be available for you to use, but will not be configured by default.

Below is the original text of the announcement, but we're not making any high impact changes here for RC2.

Summary

We're making some improvements in RC2 to the Antiforgery package package to provide more sensible defaults and support usage outside of MVC. The Antiforgery package helps your protect against CSRF (also known as XSRF) vulnerabilities by requiring a server-generated token in the request.

CSRF protection is needed when a browser can make logged-in requests on a user's behalf through a form, or an image tag. A malicious website can craft a tag which will submit a request to a trusted website. This can occur when using a persistent authentication mechanism like cookie, windows-auth or basic.

With these changes we're going to detail a few strategies that can work for protecting your site from CSRF while reducing the amount of boilerplate.

History

Historically, CSRF protection has been available in MVC applications through the @Html.AntiForgeryToken() helper and [ValidateAntiForgeryToken] attribute. A developer would call @Html.AntiForgeryToken() inside every <form> element, and slap on a [ValidateAntiForgeryToken] attribute on every action method that handles user input. This boilerplate could also be generated by scaffolding, so if you were using the tools it would be done for you.

This Razor Code:

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    <input type="submit" value="Submit" />
}

Yields:

<form action="/" method="post">
    <input name="__RequestVerificationToken" type="hidden" value="CfDJ8Huz....">
    <input type="submit" value="Submit">
</form>

And is validated by:

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult HandleInput()
{
    ...
}

Uh oh

The problem with this approach of course is that you need to know about it in order to be protected. You also have to remember to put these calls on both ends (the form, and the handling action).

Changes

The first step towards improving the status quo is to make it automatic. We've made the <form> TagHelper and @Html.BeginForm include a token by default when the action is anything other than GET. You can suppress the token if you have a scenario where you don't want it.


We've also added a smarter version of [ValidateAntiForgeryToken] - [AutoValidateAntiforgeryToken].

This new attribute is a filter that expect you to apply at the global level (your whole site). The filter validates a token for unsafe (DELETE, PUT, POST, ...) HTTP methods, and does not attempt to validate a token for safe HTTP methods (GET, HEAD, OPTIONS, TRACE).

See the recommendations below. We strongly discourge making any mutations to your site's state for HTTP methods like GET.


We've also added a middleware, which plugs into the authentication system. Any request using an unsafe (DELETE, PUT, POST, ...) HTTP method will not be considered authentic unless it includes a valid token. That is, the user is not considered "logged in" unless a valid token is provided.

The advantage of using middleware is that it makes it possible to support both cookie auth (with antiforgery) and bearer-token auth (without antiforgery) on the same endpoints if desired.


Using [ValidateAntiForgery] of course still works.

Recommendations

First of all make sure that your site doesn't mutate state on any safe HTTP methods (GET, HEAD, OPTIONS, TRACE). This is a general bad practice to avoid, and can be a source of CSRF vulnerabilities.

Secondly, look for endpoints that allow anonymous user input. These are generally things like a "login" or "register" action. Place [ValidateAntiForgeryToken] on these actions if using MVC, otherwise call IAntiforgery.ValidateRequestAsync. Our templated versions of this code for user management always include [ValidateAntiForgeryToken]. This will work with any strategy.


From here consider one of the following options:

Using Antiforgery Middleware

This is the strategy that our templates (with authentication) use. The UseAntiforgery() must come after authentication middleware that you want to protect.

Requests without a valid token for a "logged in" user will be treated by the auth system as "not logged in". This might mean a challenge, login screen, or unauthorized response.

public void Configure(IApplicationBuilder app)
{
    app.UseIdentity();

    // Require a token on POST/PUT/DELETE/ETC for logged in users
    app.UseAntiforgery();

    app.UseMvcWithDefaultRoute();
}

This approach composes with any middleware and doesn't require the use of MVC. Consider this the default for new projects.

Using AutoValidateAntiforgery filter

This strategy will validate all POST/PUT/DELETE/ETC requests and give a 400 response if a valid token is not included.

public void ConfigureServices(IServiceCollection services)
{
    // Require a token on POST/PUT/DELETE/ETC for logged in users
    app.AddMvc(options =>
    {
        options.Filters.Add(new AutoValidateAntiforgeryAttribute());
    });
}

This approach is MVC specific. Use this is you want to protect a site using MVC with no authentication.

Expose cookie options via Antiforgery options

With the following commit, the path of the antiforgery's cookie token is set to always use the request's PathBase. Consider exposing the cookie's options via the AntiforgeryOptions to enable users to set it explicitly if they need to.

Antiforgery token works on remote not on localhost

XSRF-TOKEN is not added on localhost in request headers.

Set-up in Startup.cs:

       public void ConfigureDevelopmentServices(IServiceCollection services)
        {
            services.AddAntiforgery(o => { o.HeaderName = "X-XSRF-TOKEN"; o.RequireSsl = false; });
            ConfigureEnvironmentAgnosticServices(services);
        }

Then in Configure method:

app.Use(next => context =>
            {
                if (
                    string.Equals(context.Request.Path.Value, "/", StringComparison.OrdinalIgnoreCase))
                {
                    var tokens = antiforgery.GetAndStoreTokens(context);
                    context.Items.Add("XSRF-TOKEN", tokens.RequestToken);
                }

                return next(context);
            });

Antiforgery middleware:

        public async Task Invoke(HttpContext context)
        {
            if (string.Equals(context.Request.Method, "POST", StringComparison.OrdinalIgnoreCase))
            {
                await _antiforgery.ValidateRequestAsync(context);
            }
            await _next.Invoke(context);
        }

Error:

AntiforgeryValidationException: The required antiforgery header value "X-XSRF-TOKEN" is not present.

XSRF type is not added in headers in localhost, so it is impossible to test it on localhost. Works on remote servers though.

Can't seem to figure out this.

How to set the cookie name?

I've tried with both ...

services.AddAntiforgery(options => 
{
    options.CookieName = "MY_X-XSRF-COOKIE";
    options.HeaderName = "MY_X-XSRF-TOKEN";
});

... and ...

services.Configure<AntiforgeryOptions>(options =>
{
    options.CookieName = "MY_X-XSRF-COOKIE";
    options.HeaderName = "MY_X-XSRF-TOKEN";
});

... but I'm only getting ...

.AspNetCore.Antiforgery.uZGDUqdnfBA=...................................; 

[EDIT] I looked at the repo tests, and this looks correct. I feel that I'm missing something simple here.

How do I use app.Map and ValidateRequestAsync with app.UseMvc?

I've been trying to get this to work for a while and find few examples. Actually this quite elegant method of antiforgery prompted me to upgrade from RC1 to RC2, which was a bit painful but everything is working now, except this.

Here is my code that is based on your angular.js example, I only have problem with the last part app.Map() that is causing the request to stop even if its a "GET" request - an empty response comes back. Any ideas?

app.Use(next => context =>
{
    if (
        string.Equals(context.Request.Path.Value, "/", StringComparison.OrdinalIgnoreCase) ||
        string.Equals(context.Request.Path.Value, "/index.html", StringComparison.OrdinalIgnoreCase))
    {
        // We can send the request token as a JavaScript-readable cookie, and Angular will use it by default.
        var tokens = antiforgery.GetAndStoreTokens(context);
        context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken, new CookieOptions() { HttpOnly = false });
    }

    return next(context);
});

// Configure the HTTP request pipeline.
app.UseDefaultFiles();
app.UseStaticFiles();

app.UseSession();

// Add MVC to the request pipeline.

app.Map("/api", a => a.Run(async context =>
{
    if (string.Equals("POST", context.Request.Method, StringComparison.OrdinalIgnoreCase))
    {
        // This will throw if the token is invalid.
        await antiforgery.ValidateRequestAsync(context);  
    }
}));

app.UseMvc();

TryValidateTokenSet null tokens don't flow well for custom use of this method

When attempting to manually generate and consume time-limited tokens (#36 (comment)), I'm using TryValidateTokenSet directly, but when either of the tokens are set to null (as I have setup in my own Deserialize method when DP says that the token is expired ... I just return null for the token), the TryValidateTokenSet method doesn't flow the result and message well for me at

Here's how null tokens are handled now. They throw ...

if (cookieToken == null)
{
    throw new ArgumentNullException(
        nameof(cookieToken),
        Resources.Antiforgery_CookieToken_MustBeProvided_Generic);
}
if (requestToken == null)
{
    throw new ArgumentNullException(
        nameof(requestToken),
        Resources.Antiforgery_RequestToken_MustBeProvided_Generic);
}

It looks like it wasn't a prob for the original specification for antiforgery, because the only null tokens are those that aren't part of the request in the first place. I see the tests very early on for the cookie and either header or body request token being null (missing from the request). If missing, I see they get handled prior to the validation attempt. I guess the original thinking was that in TryValidateTokenSet null would never be a "good" value to get back out of deserialization. However, that's exactly the case here.

It's better for me to return a null token from deserialization when the DP throws claiming that the token is expired. I can't very well return an actual token. ๐Ÿ˜„ Since for me, a null token is fine out of deserialization, I'd like to just have TryValidateTokenSet flow it back to the caller cleanly just like the rest of the validation failures there ...

if (cookieToken == null)
{
    message = Resources.Antiforgery_CookieToken_MustBeProvided_Generic;
    return false;
}
if (requestToken == null)
{
    message = Resources.Antiforgery_RequestToken_MustBeProvided_Generic;
    return false;
}

I realize I can replace the method, but it would make it easier to consume the result of this OOB method if it were built-in. I would like to just do this ...

if (!tokenGenerator.TryValidateTokenSet(
    HttpContext,
    deserializedCookieToken,
    deserializedRequestToken,
    out message))
{
    // Log message here
    return HttpStatusCode.BadRequest;
}
return HttpStatusCode.OK;

but if I don't replace this method, then I'm stuck having to do this ...

try
{
    if (!tokenGenerator.TryValidateTokenSet(
        HttpContext,
        deserializedCookieToken,
        deserializedRequestToken,
        out message))
    {
        // Log message here
        return HttpStatusCode.BadRequest;
    }
}
catch (System.Exception ex)
{
    // Log exception here (for me, this will prob be an expired token out of DP)
    return HttpStatusCode.BadRequest;
}
return HttpStatusCode.OK;

Antiforgery token for a different claims-based user than the current user

Hi

In my single-page application using ajax requests I need to sign-in user using ajax (with antiforgery token provided by GetAndStoreTokens()) - all nice and well, but after the sign-in subsequent requests fail with error: "The provided antiforgery token was meant for a different claims-based user than the current user."
So of course I tried to return new token (using GetAndStoreTokens()) at the end of sign-in request, but it still doesn't work. My understanding of the source code is that Antiforgery service is not updating cookies if they are already set, regardless if they are still valid or not. How can I update the antiforgery tokens after the user signs in?

Access null object in Microsoft.AspNetCore.Antiforgery.Internal.DefaultAntiforgeryTokenSerializer.Deserialize

When I ran my app with debugger attached on Linux, I always hit fault on accessing invalid address. It turned out due to missing antiforgery cookie in the client request. So basically the test client faked requests and avoided using antiforgery token. The server code handling this is not checking whether this cookie exists or not before handling to deserializer.

Process 42821 stopped
* thread #15: tid = 42953, 0x00007fff7e0db40e, name = 'StarterMvc', stop reason = invalid address (fault address: 0x8)
    frame #0: 0x00007fff7e0db40e
-> 0x7fff7e0db40e: movl   0x8(%rbx), %r14d
   0x7fff7e0db412: movl   %r14d, %edi
   0x7fff7e0db415: callq  0x7fff7e0c5c90
   0x7fff7e0db41a: movl   %eax, %esi
(lldb) bt
* thread #15: tid = 42953, 0x00007fff7e0db40e, name = 'StarterMvc', stop reason = invalid address (fault address: 0x8)
  * frame #0: 0x00007fff7e0db40e
    frame #1: 0x00007fff7e0daeab
    frame #2: 0x00007fff7e0dad84
    frame #3: 0x00007fff7e0dab6e
    frame #4: 0x00007fff7e0da86e
    frame #5: 0x00007fff7e0da383
  โ€ฆ
    frame #90: 0x00007fff7c9d3215
    frame #91: 0x00007ffff6420fa7 libcoreclr.so`CallDescrWorkerInternal + 124
    frame #92: 0x00007ffff633c09e libcoreclr.so`MethodDescCallSite::CallTargetWorker(unsigned long const*) + 862
    frame #93: 0x00007ffff6538a0a libcoreclr.so`QueueUserWorkItemManagedCallback(void*) + 186
    frame #94: 0x00007ffff630ff8e libcoreclr.so`ManagedThreadBase_DispatchOuter(ManagedThreadCallState*) + 430
    frame #95: 0x00007ffff6310736 libcoreclr.so`ManagedThreadBase::ThreadPool(ADID, void (*)(void*), void*) + 70
    frame #96: 0x00007ffff651a974 libcoreclr.so`ManagedPerAppDomainTPCount::DispatchWorkItem(bool*, bool*) + 292
    frame #97: 0x00007ffff632e8ec libcoreclr.so`ThreadpoolMgr::WorkerThreadStart(void*) + 1228
    frame #98: 0x00007ffff67d96c9 libcoreclr.so`CorUnix::CPalThread::ThreadEntry(pvParam=0x0000000000832cf0) + 297 at thread.cpp:1641
    frame #99: 0x00007ffff79c0182 libpthread.so.0`start_thread + 194
    frame #100: 0x00007ffff6ecd47d libc.so.6`clone + 109

The missing stacks are managed stack:

(lldb) clrstack
OS Thread Id: 0xa7c9 (15)
        Child SP               IP Call Site
00007FFF5FFFA6E0 00007FFF7E0DB40E Microsoft.AspNetCore.Antiforgery.Internal.DefaultAntiforgeryTokenSerializer.Deserialize(System.String)
00007FFF5FFFA730 00007FFF7E0DAEAB Microsoft.AspNetCore.Antiforgery.Internal.DefaultAntiforgery.GetCookieTokenDoesNotThrow(Microsoft.AspNetCore.Http.HttpContext)
00007FFF5FFFA760 00007FFF7E0DAD84 Microsoft.AspNetCore.Antiforgery.Internal.DefaultAntiforgery.GetCookieTokens(Microsoft.AspNetCore.Http.HttpContext)
00007FFF5FFFA790 00007FFF7E0DAB6E Microsoft.AspNetCore.Antiforgery.Internal.DefaultAntiforgery.GetTokensInternal(Microsoft.AspNetCore.Http.HttpContext)
00007FFF5FFFA7C0 00007FFF7E0DA86E Microsoft.AspNetCore.Antiforgery.Internal.DefaultAntiforgery.GetAndStoreTokens(Microsoft.AspNetCore.Http.HttpContext)
00007FFF5FFFA7F0 00007FFF7E0DA383 Microsoft.AspNetCore.Mvc.ViewFeatures.AntiforgeryExtensions.GetHtml(Microsoft.AspNetCore.Antiforgery.IAntiforgery, 

In the code:

        private AntiforgeryToken GetCookieTokenDoesNotThrow(HttpContext httpContext)
        {
            try
            {
                var serializedToken = _tokenStore.GetCookieToken(httpContext);
                var token = _tokenSerializer.Deserialize(serializedToken);

                return token;
            }
            catch
            {
                // ignore failures since we'll just generate a new token
                return null;
            }
โ€ฆ
        public AntiforgeryToken Deserialize(string serializedToken)
        {
            var serializationContext = _pool.Get();

            Exception innerException = null;
            try
            {
                var count = serializedToken.Length;

Although this exception would be captured and ignored, it incurs extra cost, and could be easily avoided by checking if the searializedToken is null.

Can't build on OSX

Downloading KoreBuild from https://github.com/aspnet/KoreBuild/archive/dev.zip
Building /Users/dfowler/dev/Universe/Antiforgery
dotnet_install: Preparing to install .NET Tools from 'beta' channel to '/Users/dfowler/.dotnet'
dotnet_install: You already have the version 1.0.0.001718.
log  : Restoring packages for /Users/dfowler/dev/Universe/Antiforgery/.build/project.json...
log  : Installing xunit.abstractions 2.0.0.
log  : Installing xunit.extensibility.execution 2.1.0.
log  : Installing xunit.extensibility.core 2.1.0.
log  : Installing NuGetPackageVerifier 1.0.1-rc2-15044.
log  : Installing xunit.core 2.1.0.
log  : Installing xunit.runner.console 2.1.0.
log  : Installing Sake 0.2.2.
log  : .build/project.json
log  : Restore completed in 2129ms.
info: Run target: default
info: Run target: pre-clean
info: Run target: target-dir-clean
info: Run target: clean
info: Run target: post-clean
info: Run target: validate
info: Run target: restore-npm-modules
info: Testing for command: node --version
warn:    command exception: System.ComponentModel.Win32Exception: ApplicationName='node', CommandLine='--version', CurrentDirectory='', Native error= Cannot find the specified file
  at System.Diagnostics.Process.Start_noshell (System.Diagnostics.ProcessStartInfo startInfo, System.Diagnostics.Process process) [0x00000] in <filename unknown>:0
  at System.Diagnostics.Process.Start_common (System.Diagnostics.ProcessStartInfo startInfo, System.Diagnostics.Process process) [0x00000] in <filename unknown>:0
  at System.Diagnostics.Process.Start (System.Diagnostics.ProcessStartInfo startInfo) [0x00000] in <filename unknown>:0
  at View40283d0c75a2426fb51406ae3a1a1d15.TestCommand (System.String program, System.String commandline) [0x00000] in <filename unknown>:0
warn:    command not found
info: Exec
info:   program: npm
info:   commandline: install --quiet --depth 0
info:   workingdir: /Users/dfowler/dev/Universe/Antiforgery/samples/AntiforgerySample
fail: One or more errors occurred.
fail: Stack trace:
  at System.Threading.Tasks.Task.ThrowIfExceptional (Boolean includeTaskCanceledExceptions) [0x00000] in <filename unknown>:0
  at System.Threading.Tasks.Task.Wait (Int32 millisecondsTimeout, CancellationToken cancellationToken) [0x00000] in <filename unknown>:0
  at System.Threading.Tasks.Task.Wait () [0x00000] in <filename unknown>:0
  at System.Threading.Tasks.Parallel.ForWorker[Object] (Int32 fromInclusive, Int32 toExclusive, System.Threading.Tasks.ParallelOptions parallelOptions, System.Action`1 body, System.Action`2 bodyWithState, System.Func`4 bodyWithLocal, System.Func`1 localInit, System.Action`1 localFinally) [0x00000] in <filename unknown>:0
Davids-MacBook-Pro:Antiforgery dfowler$

/cc @dougbu @victorhurdugaci @pranavkm

Invalidate Tokens

I'm using Antiforgery for a site we're building for a large insurer, I just received the results of a security audit, the auditor insists the request token should be invalidated on each request. I cannot find a way to enforce new tokens for every request. Can someone tell me if this is possible and how? If its not possible would you consider adding it?

Review generation of UID in DefaultClaimUidExtractor

According to @blowdart and @lodejard the way we generate the UID for a ClaimsPrincipal is wrong in antiforgery.

We should use the ClaimsIdentity.NameClaimType of all authenticated identities to generate the UID rather than looking for a claim of type ClaimTypes.NameIdentifier.

We need to also figure out the right thing to do (or if it's possible) when the user does not have a name.

Consider throwing a 400 instead of a 500

Not sure if it should be here or in MVC, but this seems like the right place.

I'm playing around with getting this to work for API calls. I notice that when I don't deliver an anti forgery token, the request results in a 500. Maybe this is just me, but shouldn't this be a 400? The server shouldn't fail (and log a 500) simply because I (or any other third party) forgets to add this token (read: bad request).

Exception I get is:

 An unhandled exception has occurred: The required antiforgery form field "__RequestVerificationToken" is not present.
      System.InvalidOperationException: The required antiforgery form field "__RequestVerificationToken" is not present.
         at Microsoft.AspNet.Antiforgery.DefaultAntiforgeryTokenStore.<GetRequestTokensAsync>d__4.MoveNext()
      --- End of stack trace from previous location where exception was thrown ---
         at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
         at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
         at Microsoft.AspNet.Antiforgery.DefaultAntiforgery.<ValidateRequestAsync>d__9.MoveNext()
      --- End of stack trace from previous location where exception was thrown ---
         at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
         at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
         at Microsoft.AspNet.Mvc.Controllers.FilterActionInvoker.<InvokeAuthorizationFilterAsync>d__47.MoveNext()
      --- End of stack trace from previous location where exception was thrown ---
         at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
         at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
         at Microsoft.AspNet.Mvc.Controllers.FilterActionInvoker.<InvokeAuthorizationFilterAsync>d__47.MoveNext()
      --- End of stack trace from previous location where exception was thrown ---
         at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
         at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
         at Microsoft.AspNet.Mvc.Controllers.FilterActionInvoker.<InvokeAsync>d__44.MoveNext()
      --- End of stack trace from previous location where exception was thrown ---
         at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
         at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
         at Microsoft.AspNet.Mvc.Infrastructure.MvcRouteHandler.<RouteAsync>d__6.MoveNext()
      --- End of stack trace from previous location where exception was thrown ---
         at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
         at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
         at Microsoft.AspNet.Mvc.Routing.InnerAttributeRoute.<RouteAsync>d__10.MoveNext()
      --- End of stack trace from previous location where exception was thrown ---
         at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
         at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
         at Microsoft.AspNet.Routing.RouteCollection.<RouteAsync>d__9.MoveNext()
      --- End of stack trace from previous location where exception was thrown ---
         at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
         at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
         at Microsoft.AspNet.Builder.RouterMiddleware.<Invoke>d__4.MoveNext()
      --- End of stack trace from previous location where exception was thrown ---
         at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
         at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
         at Microsoft.AspNet.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
      --- End of stack trace from previous location where exception was thrown ---
         at Microsoft.AspNet.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
      --- End of stack trace from previous location where exception was thrown ---
         at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
         at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
         at Microsoft.AspNet.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
      --- End of stack trace from previous location where exception was thrown ---
         at Microsoft.AspNet.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
      --- End of stack trace from previous location where exception was thrown ---
         at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
         at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
         at Microsoft.AspNet.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
      --- End of stack trace from previous location where exception was thrown ---
         at Microsoft.AspNet.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
      --- End of stack trace from previous location where exception was thrown ---
         at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
         at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
         at Microsoft.AspNet.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
      --- End of stack trace from previous location where exception was thrown ---
         at Microsoft.AspNet.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
      --- End of stack trace from previous location where exception was thrown ---
         at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
         at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
         at Microsoft.AspNet.IISPlatformHandler.IISPlatformHandlerMiddleware.<Invoke>d__8.MoveNext()
      --- End of stack trace from previous location where exception was thrown ---
         at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
         at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
         at Microsoft.AspNet.Diagnostics.ExceptionHandlerMiddleware.<Invoke>d__6.MoveNext()

Correct usage of AntiForgery token in ASP.NET 5 in SPA application?

In previous version of ASP.NET during SPA application the idea of AntiForgey token was following:

  • add @Html.AntiForgeryToken(); on the page
  • add __RequestVerificationToken to the request
  • override AuthorizeAttribute as ValidateJsonAntiForgeryTokenAttribute.

I don't really understand the authorization requirements (is there some good information source?) in ASP.NET 5 but looks like new behavior should be like this:

  • add asp-anti-forgerytaghelper
  • add __RequestVerificationToken to the request
  • here should be the new requirement.

The question is: how to write this new authorization requirement and remove standard one?
Could someone give some advice or point me on some example? Thanks

P.S. Looks like I need to create custome middleware and check if it's json to use my way or use standard await _antiforgery.ValidateRequestAsync(context);
But still not sure about it.

Antiforgery Token used by AngularJS

I was trying to follow the sample code provided for AntiForgery
There anti-forgery token is written to a cookie where AngularJS (Javascript) can read it and use it on every subsequent XHR requests.

I see that even when the same token is used more than once, It is considered to be a valid token and everything is just normal. When and how an issued token gets invalid?

If the token can be used more than once, how is it secure to use it with AngularJS (Javascript)?
What happens if malicious code get access to this token?

Setting the Machine Key as usual? ... or any other gotchas for web farm scenarios?

We'll be setting the Machine Key as usual for .NET 5 apps using Antiforgery in web farm scenarios, correct?

If so, this might be a feature request: Any interest in providing some control of the Machine Key somewhere in Startup.cs (or does that already exist)? Continuing to use web.config sucks, and IIS settings are inconvenient.

Besides the Machine Key, are there any other gotchas we should be aware of with Antiforgery in a web farm scenario?

Antiforgery for AJAX calls

It would be nice that ValidateAntiForgeryTokenAttribute (or DefaultAntiforgeryTokenStore) search token in headers too, not only in values posteds from forms.

So we can easily apply CSRF protection in Ajax calls to REST services (angularjs or jquery apps).

Handling a failed validation

When I use UseStatusCodePagesWithReExecute and get a 404 is there any way I can know that the cause is that the validation of the antiforgery token failed?

I tried getting this information via Features but it was no success:

[Route("~/Error/{code}")]
public IActionResult Error(string code /*400 when validation failed*/)
{
    var itsNull1 = HttpContext.Features.Get<IAntiforgery>();
    var itsNull2 = HttpContext.Features.Get<IAntiforgeryAdditionalDataProvider>();
    var itsNull3 = HttpContext.Features.Get<IAntiforgeryFeature>();
    var itsNull4 = HttpContext.Features.Get<AntiforgeryFeature>();
    var itsNull5 = HttpContext.Features.Get<AntiforgeryValidationException>();

    var status = Response.StatusCode; // 200 when validation failed
    ...

One thing I found is that normally the following is true inside the Error action: code = Response.StatusCode.ToString(). It's true for instance when I return a 400 StatusCodeResult myself from an action. Now when the Error action is executed because the token validation failed then code is "400" and Response.StatusCode is 200 for some reason.

Is it safe to assume that when code == "400" && Response.StatusCode == 200 Antiforgery is responsible?

How to use Antiforgery with a JS client on separate subdomain?

Hi Everyone

I have an ASP.NET Core backend with some Web APIs, and an AngularJS client on separate subdomains (Actually on localhost with different ports), and I can't seem to get Antiforgery to work.

I get 400 Bad request response on APIs protected with [ValidateAntiForgeryToken], this is my backend code :

services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");

...

app.Use(next => context => {
	tokens = antiforgery.GetAndStoreTokens(context);
	context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken, new CookieOptions { HttpOnly = false });
	return next(context);
});

First problem i've got is that the cookie is not set on my AngularJS app, i've resolved it by setting WithCredentials to true : $httpProvider.defaults.withCredentials = true;

The second one is that the X-XSRF-TOKEN header is not set automatically by AngularJS, and i've solved it by setting an interceptor : config.headers['X-XSRF-TOKEN'] = $cookies.get('XSRF-TOKEN');

Now I can receive the token and send it with my $http requests, I don't understand why API calls are rejected ! Is it related that the applications are not on the same port ?

Thanks in advance :)

Improve the performance of Antiforgery

Right now the cost of using @Html.Antiforgery is about 7.5kb / request. In the context of a small MVC form, this is about 15% of the total bytes. We can do much better.

Some places to start looking.

Strings:
image

Bytes:
image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.