I'm trying to implement AntiForgeryToken in our existing Web application which is ASP.Net MVC 5 application with AngularJS front end.
Following is the code for my BaseFilter:
public class BaseFilter : ActionFilterAttribute
{
private const string CLAIM_TYPE_EMAILADDRESS =
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress";
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
Debug.WriteLine("Base filter started at ={0}", DateTime.Now.ToString());
var baseController = filterContext.Controller as BaseController;
var routeData = filterContext.RouteData;
var controller = routeData.Values["controller"].ToString();
var action = routeData.Values["action"].ToString();
if (baseController != null)
{
var claims1 = ClaimsPrincipal.Current.Identities.First();
var emailId1 = claims1.Claims.FirstOrDefault(x => x.Type == CLAIM_TYPE_EMAILADDRESS).Value;
var roleName=claims1.Claims.FirstOrDefault(x => x.Type == "Role").Value;
baseController.GetCurrentUser();
if (roleName == "Freemium")
{
baseController.GetFreemiumDaysLeft(emailId1);
}
}
//Calls should be made only in case of Page Request instead of Ajax Request
if (!filterContext.HttpContext.Request.IsAjaxRequest())
{
if (filterContext.HttpContext.Request.QueryString["contractId"] != null)
{
var contractId =
Convert.ToInt32(new EncryptDecrypt().DecryptString(filterContext.HttpContext.Request.QueryString["contractId"]));
if (baseController != null)
{
baseController.GetContractProgressStatus(contractId, controller, filterContext);
}
}
else
{
if (
controller != "Dashboard" &&
controller != "UserRegistration" &&
controller != "Help" &&
controller != "BasicInfo" && action == "Index")
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary
{
{"controller", "BasicInfo"},
{"action", "Index"}
});
}
}
//if(controller)
string cookieToken = "";
string formToken = "";
if (filterContext.HttpContext.Request.HttpMethod != "GET")
{
var tokenHeaders = filterContext.HttpContext.Request.Headers.GetValues("RequestVerificationToken").FirstOrDefault();
if (tokenHeaders != null)
{
string[] tokens = tokenHeaders.Split(':');
if (tokens.Length == 2)
{
cookieToken = tokens[0].Trim();
formToken = tokens[1].Trim();
}
}
System.Web.Helpers.AntiForgery.Validate(cookieToken, formToken);
}
base.OnActionExecuting(filterContext);
}
}
Following is the AntiForgery extension:
public static class AntiForgeryExtension
{
public static string RequestVerificationToken(this HtmlHelper helper)
{
return String.Format("__RequestVerificationToken={0}", GetTokenHeaderValue());
}
private static string GetTokenHeaderValue()
{
string cookieToken, formToken;
System.Web.Helpers.AntiForgery.GetTokens(null, out cookieToken, out formToken);
return cookieToken + ":" + formToken;
}
}
Following is my Index.cshtml:
@using MyProj.Web.AuthData
<script src="~/Scripts/DashboardVersion.js"></script>
<!-- Page header -->
<div class="page-header page-header-ey-default title-height">
<div class="page-header-content">
<div class="page-title">
</div>
</div>
</div>
<!-- /page header -->
<section>
<div>
<div class="clear1"></div>
<div ng-app="dashboardVersion" ng-controller="DashboardController" ng-cloak data-ng-init="antiForgeryToken='@Html.RequestVerificationToken()'">
</div>
</div>
</section>
Following is the index.js post call:
$scope.saveVersion = function () {
if ($scope.SaveVersion.VersionName === undefined || $scope.SaveVersion.VersionName.toString().trim() === "") {
showWarning("Please enter scenario name.");
return;
}
else if (_.find($scope.VersionsLowercase,
{ VersionName: $scope.SaveVersion.VersionName.toString().toLowerCase().trim() })) {
showWarning("Version with similar name already exists.");
}
else {
var token = $scope.antiForgeryToken;
var headers = {
headers: {
'RequestVerificationToken': token
}};
$scope.SaveVersion.VersionName = $scope.SaveVersion.VersionName.toString().trim();
$http.post("/PortfolioVersion/SaveVersion/", $scope.SaveVersion, headers).then(function (response) {
clearDirty();
$("#version-modal").modal("hide");
if (response.data == "true") {
showSuccess("data successfully saved.");
}
else if (response.data == "false") {
showError("An error occured while saving .");
}
$scope.init();
});
}
};
Following code is added to Global.asax:
AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;
I have generated the machine key manually from IIS in my machine and added it in Web.config under ...:
<machineKey
validationKey="myKey"
decryptionKey="myKey"
validation="SHA1"
decryption="AES"
/>
After adding all this, I'm getting the following error in TokenValidation:
Message=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 have followed all the answers given in the following link: The anti-forgery token could not be decrypted
But nothing seems to work for me. Please help resolve my issue.