MVC 4, AntiForgeryToken and Claims
Using Html.AntiForgeryToken in MVC 4 has changed slightly from the previous version if you’re building a claims-aware application. In prior versions User.Identity.Name was included in the anti-forgery token as a way to validate the <form> being submitted, but in MVC 4 if the identity is IClaimsIdentity (WIF) or ClaimsIdentity (.NET 4.5) then the anti-forgery token attempts to put one or more claim values into the anti-forgery token.
The problem is which claim(s) should it use? The value needs to uniquely identifier the user, so by default MVC expects the nameidentifier (“http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier” from OASIS) and the identityprovider (“http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider” from Windows Azure ACS). So if you’re using ACS as your STS then you’re all set. If you’re not using ACS then you’ll see this error:
A claim of type ‘http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier’ or ‘http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider’ was not present on the provided ClaimsIdentity. To enable anti-forgery token support with claims-based authentication, please verify that the configured claims provider is providing both of these claims on the ClaimsIdentity instances it generates. If the configured claims provider instead uses a different claim type as a unique identifier, it can be configured by setting the static property AntiForgeryConfig.UniqueClaimTypeIdentifier.
Unfortunately this error is a little confusing because it says “nameidentifier or identityprovider” even though you may have one of the two. By default you need both.
Anyway, if you’re not using ACS as your STS then the above error pretty much tells you what’s needed to solve the problem. You need to tell MVC which claim you want to use to uniquely identify the user. You do this by setting the AntiForgeryConfig.UniqueClaimTypeIdentifier property (typically in App_Start in global.asax). For example (assuming you want to use nameidentifier as the unique claim):
using System.Web.Helpers; protected void Application_Start() { AreaRegistration.RegisterAllAreas(); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier; }
Hi Not sure if you can help.
Getting a similar issue to above. Project is using Windows Azure Access Control Service and after signing in it posts back to a page having a HTML.AntiForgeryToken. At first it complains as above but if I add your line in global.asax I then get the error saying ‘http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier’ was not found even though I believe it is/was there.
Any ideas?
Thanks
Shane
Well if you have a page that’s being posted to by ACS, you should remove the [ValidateAntiForgeryToken] since the HTML that’s posting is not from your site. The point of the anti forgery token is to prove that your website created the HTML. In this case it didn’t.
Sorry bit confusing my post, it does not post directly, it goes to another page on my site where I store the info and then I redirect to the original redirect destination so its not even a post. However the AntiForgeryToken complains with
A claim of type ‘http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier’ was not present on the provided ClaimsIdentity.
Looking at fiddler my requests are
200 POST /Account/Register?ReturnUrl=%2Fxxx%2Fcreate HTTP/1.1
Then I get a 500 Error on GET / (or which ever page it redirects too)
So weirdly its no even a post causing the error.
Confused!!!
Shane
Is there another namespace involved?
I added
using System.Web.Security;
using System.Web.Helpers;
using System.Web.WebPages;
using System.Web.Razor;
which stopped the intellisense problem with AntiForgeryConfig.UniqueClaimTypeIdentifier – but I still have an issue with ClaimTypes in ClaimTypes.NameIdentifier; not existing in the current context.
I’m NOT using AZURE and am still using .Net4 (NOT 4.5) but I am starting to use MVC4 now. (Worked OK in MVC3)
Would really appreciate help with getting this to work in MVC4!
Thanx 4 ur help!
Alan
If you’re using .NET 4.5 then it’s in the namespace System.Security.Claims.
If you’re in 4.0 then it’s in the namespace Microsoft.IdentityModel.Claims from the Microsoft.IdentityModel.dll assembly (which is WIF 1.0).
Also, it’s System.Web.Helpers.AntiForgeryConfig from System.Web.WebPages.dll, v2.0.0.0.
Hi
Thanks for the quick response!
However, while System.Web.Helpers.AntiForgeryConfig is fine, my system doesn’t like Microsoft.IdentityModel.Claims – because of the IndentityModel.
I have System.Web.Webpages in my References, (but without a version number – so I assume it isn’t v2.0.0.0 – since there are others which do have version numbers like [2.0.0.0] ).
But I don’t have any reference to Microsoft.IdentityModel.dll assembly (which is WIF 1.0).
And WIF doesn’t seem to be available via the Extension Manager or Nuget (only enhancements to WIF).
To be more specific, I am using version 4.0.30319 SP1Rel of the .Net Framework and version 10.0.40219.1 SP1Rel of VS2010.
Is there perhaps some other security bundle that I can download that might load WIF1.0 as a prerequisite?
Or perhaps an upgrade patch for 4.o users to use ACS like 4.5 users?
Thanks again for your help – I’d really like to get the AntiForgeryToken working in MVC4.
Regards
Alan
WIF 1.0 is on NuGet: https://nuget.org/packages/Microsoft.IdentityModel
GOT IT!
Muchos gracias! I really appreciate you making the time to help a dumb newbie!
I was obviously looking for the wrong name on NuGet before.
Of course, now the namespaces all work and I’m sure the AntiForgeryToken will too.
I keep seeing CLAIMS being mentioned though – do you possibly have a reference URL that you’d recommend where I can read up on the concept and try to understand what I’m working with?
THANX again – you’ve made my day and probably my weekend!
Regards
Alan
I was having this problem and this post didn’t exactly fix it, because for some reason IdentityServer was not returning the nameidentifier claim. Turns out you can use any claim and the code will work (I used Name instead, which for my application was the same). I’m assuming that as long as a claim is unique across all users it is OK to use for this. Someone please correct me if I’m wrong.
Yep, any claim that’s unique will work.
I used the name claim-type so as to get the username when I call User.Identity.Name
Using the NameIdentifier claim-type will return null for User.Identity.NAme
Many thanks, this fixed my issue.
Reblogged this on Peter Mbanugo.
Hi , After adding the line in the application_start in global.asax , I am getting another error.
An exception of type ‘System.InvalidOperationException’ occurred in System.Web.WebPages.dll but was not handled in user code
Additional information: A claim of type ‘http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier’ was not present on the provided ClaimsIdentity.
Please help. I am using Owin authentication.
Is this your issue? https://brockallen.com/2012/07/08/mvc-4-antiforgerytoken-and-claims/
Hi.After adding the line code
System.Web.Helpers.AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;
in global.asax i’m getting error :
A claim of type ‘http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier’ was not present on the provided ClaimsIdentity.
i’m using identityserver3.
Try the “sub” claim instead.
Thanks for the quick response brockallen . My solution is
AntiForgeryConfig.UniqueClaimTypeIdentifier = “sub”;
JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary();
in Startup.cs file .
AntiForgeryConfig is not available in MVC 5. How to get this fixed. This was available till MVC4
the docs are here: http://docs.asp.net/
This is exactly what I needed to get edits working in my MVC app. Cheers!