I\'m using IdentityServer4 with ASP.NET Core 2.2. On the Post Login method I have applied the ValidateAntiForgeryToken. Generally after 20 minutes to 2 hours of sitting on the l
Since ASP.Net Core 3.0 MS decided to make ValidateAntiforgeryTokenAuthorizationFilter
internal. Now we have to copy-paste their code, to be able to derive. But most likely we don't need to. To just change the resulting behavior all we need is to test the context for the IAntiforgeryValidationFailedResult
and proceed accordantly, as described in this example.
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Core.Infrastructure;
using Microsoft.AspNetCore.Mvc.Filters;
namespace BasicWebSite.Filters
{
public class RedirectAntiforgeryValidationFailedResultFilter : IAlwaysRunResultFilter
{
public void OnResultExecuting(ResultExecutingContext context)
{
if (context.Result is IAntiforgeryValidationFailedResult result)
{
context.Result =
new RedirectResult("http://example.com/antiforgery-redirect");
}
}
public void OnResultExecuted(ResultExecutedContext context)
{ }
}
}
Then within the controller:
// POST: /Antiforgery/LoginWithRedirectResultFilter
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
[TypeFilter(typeof(RedirectAntiforgeryValidationFailedResultFilter))]
public string LoginWithRedirectResultFilter(LoginViewModel model)
{
return "Ok";
}
Yet another implementation using the default one including all prechecks, logging etc. And it's still an AuthorizationFilter
, so that prevents any further action execution. The only difference is that it triggers HttpGet
to the same url instead of the default 400 response, a kind of the Post/Redirect/Get pattern implementation.
public class AnotherAntiForgeryTokenAttribute : TypeFilterAttribute
{
public AnotherAntiForgeryTokenAttribute() : base(typeof(AnotherAntiforgeryFilter))
{
}
}
public class AnotherAntiforgeryFilter:ValidateAntiforgeryTokenAuthorizationFilter,
IAsyncAuthorizationFilter
{
public AnotherAntiforgeryFilter(IAntiforgery a, ILoggerFactory l) : base(a, l)
{
}
async Task IAsyncAuthorizationFilter.OnAuthorizationAsync(
AuthorizationFilterContext ctx)
{
await base.OnAuthorizationAsync(ctx);
if (ctx.Result is IAntiforgeryValidationFailedResult)
{
// the next four rows are optional, just illustrating a way
// to save some sensitive data such as initial query
// the form has to support that
var request = ctx.HttpContext.Request;
var url = request.Path.ToUriComponent();
if (request.Form?["ReturnUrl"].Count > 0)
url = $"{url}?ReturnUrl={Uri.EscapeDataString(request.Form?["ReturnUrl"])}";
// and the following is the only real customization
ctx.Result = new LocalRedirectResult(url);
}
}
}