I am working on a dotnet core API 6.0 with separate machine to serve Angular 13 application.
I am trying to secure my application with CSRF-Token. I am setting XSRF-TOKEN cookie from C# and withCredentials as true in Angular app, also sending header X-XSRF-TOKEN with same value as we have for XSRF-TOKEN cookie.
Added below code but its failing xsrf token validation when I hit any api endpoint with X-XSRF-TOKEN header in my request and returning 400.
Startup.cs > ConfigureServices Method
services.AddAntiforgery(options =>
{
options.HeaderName = "X-XSRF-TOKEN";
}); //Preventing Cross-Site Request Forgery (XSRF/CSRF) Attacks in ASP.NET Core
services.AddMvc(o =>
{
o.Filters.Add(new AutoValidateAntiforgeryTokenAttribute()); // adding auto validation of Antiforgery Token.
});
Startup.cs > Configure Method
app.Use(next => context =>
{
string path = context.Request.Path.Value;
if (path != null && path.ToLower().Contains("/api"))
{
var tokens = antiforgery.GetAndStoreTokens(context);
context.Response.Cookies.Append(appSettings.XSRFCookieName, tokens.RequestToken,
new CookieOptions()
{
//Path = "/",
SameSite = Microsoft.AspNetCore.Http.SameSiteMode.None,
HttpOnly = false, // a special kind of cookie that’s only sent in HTTP requests to the server, and it’s never accessible (both for reading or writing) from JavaScript running in the browser.
Secure = true, // true is used to send cookie to browser otherwise it would not be sent to browser //env.IsDevelopment() ? false : true, // if true, means it can be sent over https(SSL) only.
IsEssential = true,
Expires = DateTime.UtcNow.AddMinutes(appSettings.JwtSettings.MinutesToExpiration),
});
}
return next(context);
});
Angular
@Injectable()
export class JwtInterceptor implements HttpInterceptor {
constructor(private authenticationService: AuthenticationService, private tokenExtractor: HttpXsrfTokenExtractor) {}
intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
const xsrfToken = this.tokenExtractor.getToken() as string;
const AllowCredentialsVal = true;
var headers = new HttpHeaders({
//Authorization: `Bearer ${currentUser.jwtToken}`,
'X-XSRF-TOKEN': xsrfToken, //can be handled in app.module to auto set this header using browser cookie when both API and Agular app are on same server with cookie options as Path = / and httpOnly = false.
//'RequestVerificationToken': xsrfToken,
'Access-Control-Allow-Origin': GlobalConstants.BASE_API_URL, // Website you wish to allow to connect
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS, PUT, PATCH, DELETE', // Request methods you wish to allow
'Access-Control-Allow-Headers': 'X-Requested-With,content-type', // Request headers you wish to allow
'Access-Control-Allow-Credentials': `${AllowCredentialsVal}`, // Set to true if you need the website to include cookies in the requests sent to the API
});
request = request.clone({
headers,
withCredentials: AllowCredentialsVal,
});
// Pass to next layer of middleware
return next.handle(request);
}
Below are request header and cookies from browser's network tab, X-XSRF-TOKEN header and XSRF-TOKEN cookie has same value. Not sure what is missing, can someone please help, TIA.