Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Anti forgery system on ASP.Net MVC

Tags:

c#

asp.net-mvc

When I'm putting following code:

 @using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm" }))
    {
        @Html.AntiForgeryToken()
        <a href="javascript:document.getElementById('logoutForm').submit()">Log off</a>
    }

the

@Html.AntiForgeryToken()

part is thrownig following exception:

The provided identity of type 'System.Web.Security.FormsIdentity' is marked IsAuthenticated = true but does not have a value for Name. By default, the anti-forgery system requires that all authenticated identities have a unique Name. If it is not possible to provide a unique Name for this identity, consider setting the static property AntiForgeryConfig.AdditionalDataProvider to an instance of a type that can provide some form of unique identifier for the current user.

I've checked many examples and tried to search the web, but I cannot find any explanation. I would like to know why this error happens to me? And how to solve it to use antiforgery.

like image 740
Marcin Avatar asked Oct 09 '12 08:10

Marcin


People also ask

What is anti-forgery token in MVC?

To help prevent CSRF attacks, ASP.NET MVC uses anti-forgery tokens, also called request verification tokens. The client requests an HTML page that contains a form. The server includes two tokens in the response. One token is sent as a cookie. The other is placed in a hidden form field.

What is CSRF in asp net?

Take advantage of anti-forgery tokens in ASP.NET Core to protect users of your applications against cross site request forgery exploits. Who_I_am / Getty Images. Cross-site request forgery (CSRF) is an attack that tricks an end user into executing undesirable actions while logged into a web application.

Why are use HTML AntiForgeryToken ()?

This is to prevent Cross-site request forgery in your MVC application. This is part of the OWASP Top 10 and it is vital in terms of web security. Using the @Html. AntiforgeryToken() method will generate a token per every request so then no one can forge a form post.


2 Answers

It's telling you that it won't work because despite being logged in, Membership.GetUser().UserName is not providing a name that can be used for hashing.

So your real problem is, "How come my logged in user doesn't have a username?"

like image 94
spender Avatar answered Sep 17 '22 12:09

spender


There can be some cases when logged in user doesn't have Identity.Name set (in my case I have to integrate my app with some crazy log-in system). Then there are two ways around:

1) unsecure - all users will be treated the same way by antiforgery system regardless of their auth status

// System.Web.WebPages.dll
using System.Web.Helpers;

// not a production solution
public class MvcApplication : HttpApplication {
  protected void Application_Start() {
    AntiForgeryConfig.SuppressIdentityHeuristicChecks = true;
  }
}

2) secure - provide your own (custom) way how you distinguish your users

using System;
using System.Globalization;
using System.Web;
using System.Web.Helpers;

public class ContoscoAntiForgeryAdditionalDataProvider : IAntiForgeryAdditionalDataProvider {
  public string GetAdditionalData(HttpContextBase context) {
    if (context == null) {
      throw new ArgumentNullException("context");
    }

    var contoscoContext = new ContoscoHttpContext(context);
    int userID = contoscoContext.GetUserID().GetValueOrDefault();
    return Convert.ToString(userID, CultureInfo.InvariantCulture);
  }

  public bool ValidateAdditionalData(HttpContextBase context, string additionalData) {
    string data = GetAdditionalData(context);
    return string.Compare(data, additionalData, StringComparison.Ordinal) == 0;
  }
}


public class MvcApplication : HttpApplication {
  protected void Application_Start() {
    AntiForgeryConfig.AdditionalDataProvider = 
      new ContoscoAntiForgeryAdditionalDataProvider(); 
  }
}

where ContoscoHttpContext is class that returns UserID (or any unique user token) based on current context (i.e. HttpContextBase):

public class ContoscoHttpContext {
  private HttpContextBase _context;
  public ContoscoHttpContext(HttpContextBase context) {
    _context = context;
  }
  public int? GetUserID() {
    // TODO: provide your own implementation how to get user id
    // based on HttpContextBase stored in _context
    // in my case it was something like 
    // return ((ContoscoPrincipal)_context.User).UserID;
  }
}
like image 29
Ondrej Svejdar Avatar answered Sep 20 '22 12:09

Ondrej Svejdar