The anti-forgery token could not be decrypted
Asked Answered
R

15

81

I have a form:

@using (Html.BeginForm(new { ReturnUrl = ViewBag.ReturnUrl })) {
@Html.AntiForgeryToken()
@Html.ValidationSummary()...

and action:

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginModel model, string returnUrl, string City)
{
}

occasionally (once a week), I get the error:

The anti-forgery token could not be decrypted. If this application is hosted by a Web Farm or cluster, ensure that all machines are running the same version of ASP.NET Web Pages and that the configuration specifies explicit encryption and validation keys. AutoGenerate cannot be used in a cluster.

i try add to webconfig:

<machineKey validationKey="AutoGenerate,IsolateApps"  
    decryptionKey="AutoGenerate,IsolateApps" />

but the error still appears occasionally

I noticed this error occurs, for example when a person came from one computer and then trying another computer

Or sometimes an auto value set with incorrect data type like bool to integer to the form field by any jQuery code please also check it.

Resilience answered 1/5, 2014 at 4:53 Comment(4)
AutoGenerate will not create the same key on all machines. I'm confused why you said it can't be used, then you tried to use it.Fania
and specify it (the encryption key) specifically - can please show exampleResilience
Wouldn't "AutoGenerate" generate a new key when your application pool reloads, causing this issue when a form from an older w3wp.exe is handled by a newer w3wp.exe?Hollister
I got this error When i am Open Login Window Long Time, Then Try to Login Got this error. Just Reload this Login Window and Try to Login will Solve the Problem. But I Don't Know How to FIxTenerife
S
151

I just received this error as well and, in my case, it was caused by the anti-forgery token being applied twice in the same form. The second instance was coming from a partial view so wasn't immediately obvious.

Sigrid answered 20/2, 2015 at 2:25 Comment(10)
How can I tell if this is happening to me, and how do I fix it?Acescent
By commenting out the AntiForgery token in my partial view, I stopped getting the error. The problem is now if that partial view is used on several different pages, I don't know when to apply the AntiForgery token.Acescent
Can't you just apply the token when you initialise each form or is your solution more complex than that?Sigrid
I was also getting this error due to more than one anti-forgery token on the page (Log Off is wrapped by form element in MVC default template) but, I was doing ajax postback. Then I realised I was calling $('form').serialize() and changed that to $('#my-form-id').serialize().Braca
I know this was over a year ago, but do you recall if this was immediately obvious @SteveDowling? Today, we've been getting a tremendous amount of calls from clients reporting this "key cannot be decrypted" error. We believe it's because of multiple calls to @Html.AntiforgeryToken() from different partials, but it's weird that it hasn't been an issue for months and then suddenly we're getting bombarded with complaints...Gloriagloriana
I haven't touched this for ages but, from memory, I don't think it was obvious at all. It took a bit a of hacking to figure out what was going on.Sigrid
Can someone clarify this for me please? One of the sites I've developed has this issue, and I'm going to try and track down the rogue AntiForgeryToken, but I'm not sure if the issue is with one form containing two tokens, or one page containing two tokens. Which is it?Elisa
I think it is fine for the page to have two tokens as long as only one is being passed to the form. Check the generated HTML source and make sure each form on the page only has one hidden field containing an anti-forgery token. Search for __RequestVerificationToken in the generated page source.Sigrid
I checked all the forms on the page yesterday and couldn't find any issues - each one had only a single token. When I came in today and checked again, both instances of the site which were displaying this error are working correctly. Is it possible IIS or some worker processes had somehow screwed up? Literally nothing has changed in the code overnight.Elisa
It Helped me a lot.Helsa
A
35

validationKey="AutoGenerate"

This tells ASP.NET to generate a new encryption key for use in encrypting things like authentication tickets and antiforgery tokens every time the application starts up. If you received a request that used a different key (prior to a restart for instance) to encrypt items of the request (e.g. authenication cookies) that this exception can occur.

If you move away from "AutoGenerate" and specify it (the encryption key) specifically, requests that depend on that key to be decrypted correctly and validation will work from app restart to restart. For example:

<machineKey  
validationKey="21F090935F6E49C2C797F69BBAAD8402ABD2EE0B667A8B44EA7DD4374267A75D7
               AD972A119482D15A4127461DB1DC347C1A63AE5F1CCFAACFF1B72A7F0A281B"           
decryptionKey="ABAA84D7EC4BB56D75D217CECFFB9628809BDB8BF91CFCD64568A145BE59719F"
validation="SHA1"
decryption="AES"
/>

You can read to your heart's content at MSDN page: How To: Configure MachineKey in ASP.NET

Acceptor answered 1/5, 2014 at 5:11 Comment(4)
and specify it (the encryption key) specifically - can please show example. like validationKey="sdasdf34234defsdf+*-" decryptionKey="sdasdf34234defsdf+*-" and its key will be for all my users?Resilience
Yes, this is how requests are validated in webfarm scenarios. HTHAcceptor
I believe this is happening to me. I deploy often, and even during high-traffic times, and it seems this only occurs on app restarts/deployments.Depreciatory
Having machine id will make things complicated when we move on to new servers. When we move on to new servers, someone should consciously update the web.config file is there another option that we can tryPd
M
19

Just generate <machineKey .../> tag from a link for your framework version and insert into <system.web><system.web/> in Web.config if it does not exist.

Hope this helps.

Metaphosphate answered 14/9, 2016 at 23:44 Comment(2)
I know M$ gives the code to generate the keys.. but that link just makes life much easier. Thanks for giving location and a quick way to fix this. If mark this as the answer if it was my question :PNidianidicolous
Having machine id will make things complicated when we move on to new servers. When we move on to new servers, someone should consciously update the web.config file is there another option that we can tryPd
H
18

If you get here from google for your own developer machine showing this error, try to clear cookies in the browser. Clear Browser cookies worked for me.

Hackle answered 23/6, 2017 at 16:18 Comment(1)
Worked out for me, even in productionHalmahera
H
8

in asp.net Core you should set Data Protection system.I test in Asp.Net Core 2.1 or higher.

there are multi way to do this and you can find more information at Configure Data Protection and Replace the ASP.NET machineKey in ASP.NET Core and key storage providers.

  • first way: Local file (easy implementation)

    startup.cs content:

    public class Startup
    {
       public Startup(IConfiguration configuration, IWebHostEnvironment webHostEnvironment)
       {
           Configuration = configuration;
           WebHostEnvironment = webHostEnvironment;
       }
    
       public IConfiguration Configuration { get; }
       public IWebHostEnvironment WebHostEnvironment { get; }
    
       // This method gets called by the runtime.
       // Use this method to add services to the container.
       public void ConfigureServices(IServiceCollection services)
       {
           // .... Add your services like :
           // services.AddControllersWithViews();
           // services.AddRazorPages();
    
           // ----- finally Add this DataProtection -----
           var keysFolder = Path.Combine(WebHostEnvironment.ContentRootPath, "temp-keys");
           services.AddDataProtection()
               .SetApplicationName("Your_Project_Name")
               .PersistKeysToFileSystem(new DirectoryInfo(keysFolder))
               .SetDefaultKeyLifetime(TimeSpan.FromDays(14));
       }
    }
    
  • second way: save to db

    The Microsoft.AspNetCore.DataProtection.EntityFrameworkCore NuGet package must be added to the project file

    Add MyKeysConnection ConnectionString to your projects ConnectionStrings in appsettings.json > ConnectionStrings > MyKeysConnection.

    Add MyKeysContext class to your project.

    MyKeysContext.cs content:

    public class MyKeysContext : DbContext, IDataProtectionKeyContext
    {
       // A recommended constructor overload when using EF Core 
       // with dependency injection.
       public MyKeysContext(DbContextOptions<MyKeysContext> options) 
           : base(options) { }
    
       // This maps to the table that stores keys.
       public DbSet<DataProtectionKey> DataProtectionKeys { get; set; }
    }
    

    startup.cs content:

    public class Startup
    {
       public Startup(IConfiguration configuration)
       {
           Configuration = configuration;
       }
    
       public IConfiguration Configuration { get; }
    
       // This method gets called by the runtime.
       // Use this method to add services to the container.
       public void ConfigureServices(IServiceCollection services)
       {
           // ----- Add this DataProtection -----
           // Add a DbContext to store your Database Keys
           services.AddDbContext<MyKeysContext>(options =>
               options.UseSqlServer(Configuration.GetConnectionString("MyKeysConnection")));
    
           // using Microsoft.AspNetCore.DataProtection;
           services.AddDataProtection()
               .PersistKeysToDbContext<MyKeysContext>();
    
           // .... Add your services like :
           // services.AddControllersWithViews();
           // services.AddRazorPages();
       }
    }
    
Haler answered 23/3, 2020 at 19:8 Comment(1)
would the keys be autodeleted when their lifetime expires?Warrior
V
7

If you use Kubernetes and have more than one pod for your app this will most likely cause the request validation to fail because the pod that generates the RequestValidationToken is not necessarily the pod that will validate the token when POSTing back to your application. The fix should be to configure your nginx-controller or whatever ingress resource you are using and tell it to load balance so that each client uses one pod for all communication.

Update: I managed to fix it by adding the following annotations to my ingress:

https://kubernetes.github.io/ingress-nginx/examples/affinity/cookie/

Name    Description Values
nginx.ingress.kubernetes.io/affinity    Sets the affinity type  string (in NGINX only cookie is possible
nginx.ingress.kubernetes.io/session-cookie-name Name of the cookie that will be used    string (default to INGRESSCOOKIE)
nginx.ingress.kubernetes.io/session-cookie-hash Type of hash that will be used in cookie value  sha1/md5/index
Visit answered 20/12, 2018 at 13:56 Comment(0)
G
3

I ran into this issue in an area of code where I had a view calling a partial view, however, instead of returning a partial view, I was returning a view.

I changed:

return View(index);

to

return PartialView(index);

in my control and that fixed my problem.

Grey answered 14/12, 2015 at 18:57 Comment(0)
N
3

I got this error on .NET Core 2.1. I fixed it by adding the Data Protection service in Startup:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection();
    ....
}
Natasha answered 10/10, 2018 at 11:13 Comment(0)
U
2

you are calling more than one the @Html.AntiForgeryToken() in your view

Uncanonical answered 13/7, 2020 at 11:29 Comment(1)
thats what i want to do :D I have master page, and antiforgery in master, is always out side of page, and so out side of form. and the antiforgery in page? we need to repeat it a lot, and again it may not be inside the form which lay inside your master.Cothran
S
1

I get this error when the page is old ('stale'). A refresh of the token via a page reload resolves my problem. There seems to be some timeout period.

Sophi answered 15/11, 2017 at 18:41 Comment(0)
A
1

I found a very interesting workaround for this problem, at least in my case. My view was dynamically loading partial views with forms in a div using ajax, all within another form. the master form submits no problem, and one of the partials works but the other doesn't. The ONLY difference between the partial views was at the end of the one that was working was an empty script tag

    <script type="text/javascript">
    </script> 

I removed it and sure enough I got the error. I added an empty script tag to the other partial view and dog gone it, it works! I know it's not the cleanest... but as far as speed and overhead goes...

Antineutrino answered 13/5, 2021 at 21:10 Comment(0)
E
1

I know I'm a little late to the party, but I wanted to add another possible solution to this issue. I ran into the same problem on an MVC application I had. The code did not change for the better part of a year and all of the sudden we started receiving these kinds of error messages from the application.

We didn't have multiple instances of the anti-forgery token being applied to the view twice.

We had the machine key set at the global level to Autogenerate because of STIG requirements.

It was exasperating until I got part of the answer here: https://mcmap.net/q/50181/-how-do-i-solve-an-antiforgerytoken-exception-that-occurs-after-an-iisreset-in-my-asp-net-mvc-app:

If your MachineKey is set to AutoGenerate, then your verification tokens, etc won't survive an application restart - ASP.NET will generate a new key when it starts up, and then won't be able to decrypt the tokens correctly.

The issue was that the private memory limit of the application pool was being exceeded. This caused a recycle and, therefore, invalidated the keys for the tokens included in the form. Increasing the private memory limit for the application pool appears to have resolved the issue.

Edyth answered 30/11, 2021 at 1:21 Comment(0)
T
1

For those getting this error on Google AppEngine or Google Cloud Run, you'll need to configure your ASP.NET Core website's Data Protection.

The documentation from the Google team is easy to follow and works.

https://cloud.google.com/appengine/docs/flexible/dotnet/application-security#aspnet_core_data_protection_provider

A general overview from the Microsoft docs can be found here:

https://cloud.google.com/appengine/docs/flexible/dotnet/application-security#aspnet_core_data_protection_provider

Note that you may also find you're having to login over and over, and other quirky stuff going on. This is all because Google Cloud doesn't do sticky sessions like Azure does and you're actually hitting different instances with each request.

Other errors logged, include:

Identity.Application was not authenticated. Failure message: Unprotect ticket failed
Trichology answered 14/3, 2022 at 21:14 Comment(0)
C
0

My fix for this was to get the cookie and token values like this:

AntiForgery.GetTokens(null, out var cookieToken, out var formToken);
Cowie answered 4/6, 2020 at 10:33 Comment(0)
C
0

This error may occurred when writing wrong razor form code:

wrong: @Html.BeginForm()

correct: @using(Html.BeginForm())

Cyanogen answered 28/3 at 9:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.