5

Trying to implement AntiForgery on ASP.NET5 (aka vNext) API

All the articles I found derives from this article and uses System.Web.Helpers.AntiForgery.GetTokens which shouldn't be the way of ASP.NET5

private static string GetTokenHeaderValue() 
{
   string cookieToken, formToken;
   System.Web.Helpers.AntiForgery.GetTokens(null, out cookieToken, out formToken);
   return cookieToken + ":" + formToken;
}

Is there any implementation actually shows how to retrieve those tokens in ASP.NET5

additional source ASP.NET5 AntiForgery Source Code

0

3 Answers 3

4

Generate at Controller

using Microsoft.AspNet.Mvc;
using Microsoft.Framework.DependencyInjection;

namespace MyApp.App.Controllers
{
    public class MyController : Controller
    {
        public string GetAntiForgeryTokens()
        {
            var antiForgery = Context.RequestServices.GetService<AntiForgery>();
            AntiForgeryTokenSet antiForgeryTokenSet = antiForgery.GetTokens(Context, null);
            string output = antiForgeryTokenSet.CookieToken + ":" + antiForgeryTokenSet.FormToken;
            return output;
        }
    }    
}

Generate at View

@inject AntiForgery antiForgery
@functions
{
    public string GetAntiForgeryTokens()
    {
        AntiForgeryTokenSet antiForgeryTokenSet = antiForgery.GetTokens(Context, null);
        string output = antiForgeryTokenSet.CookieToken + ":" + antiForgeryTokenSet.FormToken;
        return output;
    }
}

<body>
    @GetAntiXsrfToken()
</body>

Validate

var antiForgery = Context.RequestServices.GetService<AntiForgery>();
antiForgery.Validate(Context, new AntiForgeryTokenSet(formToken, cookieToken));
Sign up to request clarification or add additional context in comments.

5 Comments

I believe you should re-check your code. Or make sure that nothing breaking changed since 4/18/15. The time I wrote that code there was a Context there and 3 other people also marked this answer as worked for them...
I am trying to do this in the Core1 framework. I think this is aspnet 4.6
OK but the question title is ASP NET 5
I wish I had an idea what Microsoft was planning at that time. There were no Core1 at that time as far as I remember (otherwise I would state it). I will add framework name into title right now
2

There's now a sample in the source code. The sample uses Angular 1.x. Building on that sample, by using a Filter for validation, here's a rough example. At Startup the token needs to be set:

public void Configure(IApplicationBuilder app, IAntiforgery antiforgery)
{
    app.Use(next => context =>
    {
        if (!context.Request.Path.Value.StartsWith("/api/"))
        {
            // 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);
    });
    …
}

Then a filter can be used to validate the token:

public class AntiforgeryValidationFilter : IAsyncActionFilter
{
    private readonly IAntiforgery antiforgery;

    public AntiforgeryValidationFilter(IAntiforgery antiforgery)
    {
        this.antiforgery = antiforgery;
    }

    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        if (context.HttpContext.Request.Path.Value.StartsWith("/api/"))
        {
            await antiforgery.ValidateRequestAsync(context.HttpContext);
        }
        await next();
    }
}

And then register the filter in Startup:

public void ConfigureServices(IServiceCollection services)
{
    // Angular's default header name for sending the XSRF token.
    services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");

    services
        .AddMvc(options =>
            options.Filters.Add(typeof(AntiforgeryValidationFilter)))
        …
}

4 Comments

I am trying to implement your option, yet it fails at the very first app.Use statement, where it returns the following error: Cannot convert lambda expression to intended delegate type because some of the return types in the block are not implicitly convertible to the delegate return type. What is the problem there?
@RobertJ. did you include the return next(context);? Have you tried running the Sample mentioned? It also uses the app.Use, so it might be something to work from.
I copy pasted your proposal (with minor adjustments) and it gave me the mentioned error. Could it be that I am using ASP.NET CORE RC2 version and they have changed something?
I would be surprised if that was the case, but perhaps. I'd try running their sample.
0

Another way to implement this with MVC is to use the HTML helper to get the token on the view which creates both the cookie and hidden input field token.

<form>
@Html.AntiForgeryToken()
</form>

HTML Output:

<input name="__RequestVerificationToken" type="hidden" value="*** />

Now that the form token exists, we can send the token in either the header or add it to the model that the API expects. The API can be protected with an ActionFilter which handles the custom Antiforgery token validation. Similar on how [Authorize] works

[ValidateAntiForgeryToken]
public class MyController : ApiController

The logic would be to read the headers in which the cookie and header value tokens can be found. This can then be evaluated using a call to

AntiForgery.Validate(cookieToken, headerToken);

The filter can then accept or reject the request.

Reject by returning:

HttpStatusCode.Forbidden

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.