Skip to content

MVC 4, AntiForgeryToken and Claims

July 8, 2012

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&#8221; from OASIS) and the identityprovider (“http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider&#8221; 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&#8217; or ‘http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider&#8217; 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;
}
14 Comments leave one →
  1. Shane permalink
    October 17, 2012 2:39 pm

    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

  2. October 17, 2012 2:46 pm

    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.

  3. Shane permalink
    October 17, 2012 2:57 pm

    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

  4. November 8, 2012 5:23 am

    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

    • November 8, 2012 9:45 am

      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.

      • November 9, 2012 3:52 am

        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

    • November 9, 2012 10:29 am

      WIF 1.0 is on NuGet: https://nuget.org/packages/Microsoft.IdentityModel

      • November 9, 2012 11:13 am

        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

  5. Mike permalink
    December 18, 2012 3:00 pm

    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.

    • December 18, 2012 6:44 pm

      Yep, any claim that’s unique will work.

    • March 31, 2014 7:48 am

      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

  6. Steve Newton permalink
    September 15, 2013 11:13 am

    Many thanks, this fixed my issue.

  7. March 31, 2014 7:50 am

    Reblogged this on Peter Mbanugo.

Trackbacks

  1. Visual Studio websso with MVC4, dotnet 4.5 identity model, and ACS v2 « Peter's ruminations

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: