title: How to validate AntiForgeryToken issued from one Application on different Application in .NetCore API?
body: <p>I have two Apps, ASP.NET Core Web APP ( app 1 ) and .NET CORE API ( app 2 ). I issue an AntiForgeryToken in the ( app 1 ) and return it in form as hidden field ( actually .netcore makes it automatically ). now when the user submit the form the data goes to ( app 2 ) and using CORS I was able to send the cookie of AntiForgeryToken issued by ( app 1 ) to ( app 2 ) so i can validate it and on ( app 2 ) I added the validateAntiFOrgeryToken Attribute so that I can validate it. and below is the error I receive on chrome dev tools response tab.</p>
  
  <p>I tried everything and searched all SO but this specific error cant find an answer to it.</p>
  
  <pre><code>System.InvalidOperationException: No service for type 'Microsoft.AspNetCore.Mvc.ViewFeatures.Filters.ValidateAntiforgeryTokenAuthorizationFilter' has been registered.
     at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
     at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
     at Microsoft.AspNetCore.Mvc.ValidateAntiForgeryTokenAttribute.CreateInstance(IServiceProvider serviceProvider)
     at Microsoft.AspNetCore.Mvc.Filters.DefaultFilterProvider.ProvideFilter(FilterProviderContext context, FilterItem filterItem)
     at Microsoft.AspNetCore.Mvc.Filters.DefaultFilterProvider.OnProvidersExecuting(FilterProviderContext context)
     at Microsoft.AspNetCore.Mvc.Filters.FilterFactory.CreateUncachedFiltersCore(IFilterProvider[] filterProviders, ActionContext actionContext, List`1 filterItems)
     at Microsoft.AspNetCore.Mvc.Filters.FilterFactory.GetAllFilters(IFilterProvider[] filterProviders, ActionContext actionContext)
     at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvokerCache.GetCachedResult(ControllerContext controllerContext)
     at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvokerProvider.OnProvidersExecuting(ActionInvokerProviderContext context)
     at Microsoft.AspNetCore.Mvc.Infrastructure.ActionInvokerFactory.CreateInvoker(ActionContext actionContext)
     at Microsoft.AspNetCore.Mvc.Routing.ActionEndpointFactory.&lt;&gt;c__DisplayClass7_0.&lt;CreateRequestDelegate&gt;b__0(HttpContext context)
     at Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke(HttpContext httpContext)
  --- End of stack trace from previous location where exception was thrown ---
     at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
     at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
  
  HEADERS
  =======
  Accept: application/json, text/javascript, */*; q=0.01
  Accept-Encoding: gzip, deflate, br
  Accept-Language: en-GB,en-US;q=0.9,en;q=0.8
  Cache-Control: no-cache
  Connection: close
  Content-Length: 98
  Content-Type: application/json
  Cookie: .AspNetCore.Antiforgery.P09gDl3q4JU=CfDJ8MTlw3i2dFxEnHbgYLq-NTBvWTMlXSM5JV9sH03i3b4ulUq0JlSns86jxwas797wsxz9mOS2JDlK6nhntJGc80bpNNwUyUnOQou-iTEwsykSBE7-yfc05pjknlLMNciWmrLzxHaJ-kpG8Tjnqo7jxbc
  Host: localhost:44375
  Pragma: no-cache
  Referer: https://localhost:44389/account/signup
  User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36
  origin: https://localhost:44389
  x-xsrf-token: CfDJ8MTlw3i2dFxEnHbgYLq-NTB8DUVF73lPTj3HAOL2bhD-sIDv2N4Fs0JowHt6W-WB5oQltt8ELtCH03XYq2QAxz96SYseDR-pZ6XMXAXRE8mpGUatGKtWp_yNohpbYt2ZQD25NzYqYdw-fCi3hsdQf1g
  sec-fetch-site: same-site
  sec-fetch-mode: cors
  </code></pre>
  
  <p>here is the code for app 1:</p>
  
  <p>( View )</p>
  
  <pre><code>&lt;div class="form-container"&gt;
  
      &lt;div class="form-inputs"&gt;
          &lt;form id="signup-form" method="post"&gt;
              &lt;!-- Input and Submit elements --&gt;
              @Html.AntiForgeryToken()
              &lt;input type="email" name="email" data-send="true" placeholder="Email Address" /&gt;
              &lt;span class="error"&gt;&lt;/span&gt;
              &lt;input type="password" name="password" data-send="true" placeholder="Password" data-validate="true" data-val-min="8" data-val-max="20" data-val-length-error="Password must be between 8 and 20 characters" data-val-empty-error="Password is required" /&gt;
              &lt;span class="error"&gt;&lt;/span&gt;
              &lt;input type="password" name="confirmpassword" data-send="true" data-validate="true" data-val-compare="password" data-val-empty-error="Confirm Password is required" data-val-compare-error="Password doesn't match" placeholder="Confirm Password" /&gt;
              &lt;span class="error"&gt;&lt;/span&gt;
              &lt;input type="text" name="username" placeholder="Username" data-send="true" data-validate="true" data-val-min="3" data-val-max="10" data-val-length-error="Username must be between 3 and 10 characters" data-val-empty-error="Username is required" /&gt;
              &lt;span class="error"&gt;&lt;/span&gt;
              &lt;div class="button-holder"&gt;
                  &lt;button id="signup" class="action"&gt;&lt;span id="loader"&gt;&lt;i class="fas fa-spinner"&gt;&lt;/i&gt;&lt;/span&gt;&lt;span id="button-text"&gt;signup&lt;/span&gt;&lt;/button&gt;
              &lt;/div&gt;
              &lt;div class="terms-holder"&gt;
                  &lt;p&gt;By Creating an account you agree to our &lt;span&gt;&lt;a href="#"&gt;Terms of Use&lt;/a&gt;&lt;/span&gt; and &lt;span&gt;&lt;a href="#"&gt;Privacy Policy&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
              &lt;/div&gt;
          &lt;/form&gt;
  
  
  
      &lt;/div&gt;
  &lt;/div&gt;
  </code></pre>
  
  <p>and here the code for app 2 :</p>
  
  <p>(startup.cs)</p>
  
  <pre><code>using System.Text;
  using Authentication.Models;
  using Authentication.Services;
  using Microsoft.AspNetCore.Authentication.JwtBearer;
  using Microsoft.AspNetCore.Builder;
  using Microsoft.AspNetCore.Hosting;
  using Microsoft.AspNetCore.Http;
  using Microsoft.Extensions.Configuration;
  using Microsoft.Extensions.DependencyInjection;
  using Microsoft.Extensions.Hosting;
  using Microsoft.IdentityModel.Tokens;
  
  namespace API
  {
      public class Startup
      {
          public Startup(IConfiguration configuration)
          {
              Configuration = configuration;
          }
  
          public IConfiguration Configuration { get; }
          readonly string OnlyOrigin = "OnlyOrigin";
  
          // This method gets called by the runtime. Use this method to add services to the container.
          public void ConfigureServices(IServiceCollection services)
          {
  
  
              services.AddCors(options =&gt; 
              {
                  options.AddDefaultPolicy(
                  builder =&gt; builder.WithOrigins("https://localhost:44389")
                      .AllowAnyMethod()
                      .AllowCredentials()
                      .WithHeaders("content-type","X-XSRF-TOKEN")
                      );
  
              });
              services.AddAntiforgery(options =&gt;
              {
                  // Set Cookie properties using CookieBuilder properties†.
                  options.HeaderName = "X-XSRF-TOKEN";
                  options.SuppressXFrameOptionsHeader = false;
              });
              // configure strongly typed settings objects
              var appSettingsSection = Configuration.GetSection("AppSettings");
              services.Configure&lt;AppSettings&gt;(appSettingsSection);
  
              // configure jwt authentication
              var appSettings = appSettingsSection.Get&lt;AppSettings&gt;();
              var key = Encoding.ASCII.GetBytes(appSettings.Secret);
              services.AddAuthentication(x =&gt;
              {
                  x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                  x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
              })
              .AddJwtBearer(x =&gt;
              {
                  x.RequireHttpsMetadata = false;
                  x.SaveToken = true;
                  x.TokenValidationParameters = new TokenValidationParameters
                  {
                      ValidateIssuerSigningKey = true,
                      IssuerSigningKey = new SymmetricSecurityKey(key),
                      ValidateIssuer = false,
                      ValidateAudience = false
                  };
              });
              services.AddControllers();
              services.AddScoped&lt;IAccount, AccountManager&gt;();
              services.AddSingleton&lt;IHttpContextAccessor, HttpContextAccessor&gt;();
          }
  
          // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
          public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
          {
              if (env.IsDevelopment())
              {
                  app.UseDeveloperExceptionPage();
              }
              app.UseCors();
              app.UseHttpsRedirection();
  
              app.UseRouting();
  
              app.UseAuthorization();
  
              app.UseEndpoints(endpoints =&gt;
              {
                  endpoints.MapControllers();
              });
          }
      }
  }
  </code></pre>
  
  <p>( controller ) :</p>
  
  <pre><code>using API.Models;
  using Authentication.Models;
  using Authentication.Services;
  using Microsoft.AspNetCore.Cors;
  using Microsoft.AspNetCore.Http;
  using Microsoft.AspNetCore.Mvc;
  
  namespace API.Controllers
  {
      [Route("api/authentication")]
      [ApiController]
      public class AuthenticationController : ControllerBase
      {
          private readonly IAccount accountService;
          private readonly HttpContext Context;
  
          public AuthenticationController(IAccount accountService, IHttpContextAccessor contextAccessor)
          {
              this.accountService = accountService;
              this.Context = contextAccessor.HttpContext;
          }
  
          [HttpPost]
          [Consumes("application/json")]
          [Produces("application/json")]
          [Route("account/signup")]
          //[EnableCors("Only Origin")]
          [ValidateAntiForgeryToken]
          public string Signup([FromBody] Account account)
  
          {
              if(!ModelState.IsValid)
              {
                  return "not valid";
              }
              return accountService.CreateAccount(account);
  
          }
  
          [HttpPost]
          [Consumes("application/json")]
          [Produces("application/json")]
          [Route("account/signin")]
          [ValidateAntiForgeryToken]
          public IActionResult Signin(LoginViewModel loginViewModel)
          {
              if (!ModelState.IsValid)
              {
                  return BadRequest(new Result
                  {
                      Type = "Error",
                      Return = "not valid"
                  });
              }
              Result result = accountService.Login(loginViewModel.Email, loginViewModel.Password);
              return Ok(result);
          }
  
  
  
      }
  }
  </code></pre>
  
  <p>( JQuery ) :</p>
  
  <pre><code>this.send = function () {
          alert(csrf);
          $.ajax({
              url: "https://localhost:44375/api/authentication/account/signup",
              headers: {
                  'Content-Type': 'application/json',
                  'X-XSRF-TOKEN': csrf
              },
              xhrFields: {
                  withCredentials: true
              },
              method: 'POST',
              dataType: 'json',
              data: getDataToSend(),
              success: function (data) {
                  console.log('succes: ' + data);
              }
          });
      }
  </code></pre>
  
  <p>( Request Headers ) :</p>
  
  <pre><code>:authority: localhost:44375
  :method: POST
  :path: /api/authentication/account/signup
  :scheme: https
  accept: application/json, text/javascript, */*; q=0.01
  accept-encoding: gzip, deflate, br
  accept-language: en-GB,en-US;q=0.9,en;q=0.8
  cache-control: no-cache
  content-length: 98
  content-type: application/json
  cookie: .AspNetCore.Antiforgery.P09gDl3q4JU=CfDJ8MTlw3i2dFxEnHbgYLq-NTBvWTMlXSM5JV9sH03i3b4ulUq0JlSns86jxwas797wsxz9mOS2JDlK6nhntJGc80bpNNwUyUnOQou-iTEwsykSBE7-yfc05pjknlLMNciWmrLzxHaJ-kpG8Tjnqo7jxbc
  origin: https://localhost:44389
  pragma: no-cache
  referer: https://localhost:44389/account/signup
  sec-fetch-mode: cors
  sec-fetch-site: same-site
  user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36
  x-xsrf-token: CfDJ8MTlw3i2dFxEnHbgYLq-NTB8DUVF73lPTj3HAOL2bhD-sIDv2N4Fs0JowHt6W-WB5oQltt8ELtCH03XYq2QAxz96SYseDR-pZ6XMXAXRE8mpGUatGKtWp_yNohpbYt2ZQD25NzYqYdw-fCi3hsdQf1g
  </code></pre>