I have separate frontend project in Angular 2 without using MVC and backend project is Web Api (Asp.Net Core) both are hosted on different domain. I implemented AntiForgery token functionality but it is not working.
Frontend project (UI)- http://localhost:8080/
Backend project (Web Api) - http://localhost:4823/
I am able to receive and send XSRF-Token
cookie in every request but api gives 400 Bad Request
error.
I followed this link-
Angular2 ASP.NET Core AntiForgeryToken
Startup.cs
-
public void ConfigureServices(IServiceCollection services)
{
services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
services.AddCors(options =>
{
options.AddPolicy("AllowAllCorsPolicy",
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IServiceProvider serviceProvider, IAntiforgery antiforgery)
{
app.Use(async (context, next) =>
{
if (context.Request.Path == "/")
{
//send the request token as a JavaScript-readable cookie, and Angular will use it by default
var tokens = antiforgery.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken, new CookieOptions { HttpOnly = false });
}
}
}
Controller code-
[EnableCors("AllowAllCorsPolicy")]
[ValidateAntiForgeryToken]
[Produces("application/json")]
[Route("api/Aoi")]
public class AoiController : Controller
{
...
}
Angular code-
let options = new RequestOptions({ headers: headers, withCredentials:true });
this._http.post(this.aoiUrl, bodydata, options)
.map((res: Response) => {
let data = res.json();
return data;
})
cookies can not be shared across cross domains. so even though your web api project is appending the
XSRF-TOKEN
to its context response, it is not available to your front-end application hosted in a separate domain. I saw some workarounds that used fixed cookie name in both applications by configuring the options forAddAntiforgery()
service.I think you should be able to get this working by enabling CORS. For more info, see here - https://docs.microsoft.com/en-us/aspnet/core/security/cors
Configure Antiforgery cookie like this:
I too have been looking at this lately and have done some testing and have also found a work around. The work around isn't too bad and allows you to start your development closer to a deployment scenario over working with ports.
I have found that setting up and enabling CORS in a .Net Core Web Api app will not allow you to use the built-in AntiForgeryToken mechanism. The solution that I found was to use Nginx.
Simply download Nginx and place the executable and package in a location of your choice. I use C:\nginx.
In your location, you will need to edit the Nginx config file. (./conf/nginx.conf)
In the nginx.conf file, see that your server{} part looks similar to this:
Here I list my Angular UI project ("My UI") that I have running at the root of the web server (ei:
http://localhost
)We then to list out the sockjs-node using the same url as our Angular project.
Last, I list my API project ("My Api") and in the location, I have added the
/myapi/
path. My api project will then be accessible fromhttp://localhost/myapi
and my Angular project accessible fromhttp://locahost
. Now both are using the same domain.Start up the nginx server when you are starting your development work and then start your api project and your Angular project as you normally would.
After all are running, you can navigate to your app at localhost and if you want to navigate to an endpoint in your Api project, you would go to something like
http://localhost/myapi/api/values/1
.Also notice that I have commented out the line:
proxy_set_header Connection 'upgrade';
in the nginx.conf locations and instead used:proxy_set_header Connection $http_connection;
. You will need this in order to have data sent and working properly to non-GET endpoints.Another thing to be cognizant of, from what I have found with this setup, when using the AntiforgeryToken, setting either if these in your startup.cs...
options.Filters.Add<AutoValidateAntiforgeryTokenAttribute>();
orservices.AddScoped<AutoValidateAntiforgeryTokenAttribute>();
and also using the[AutoValidateAntiforgeryToken]
class level attribute does NOT seem to kick off any validation. I have to add the[ValidateAntiForgeryToken]
attribute to methods where we want to run the Antiforgery validation. Perhaps someone can comment on that part.