I am trying to add an additional (and required) layer of security to my web-application: CSRF Token. The application uses DOTNET as backend and Vue as frontend, but I do not know where to start... I think I have successfully got which is the underlying protection mechanism provided by CSRF Tokens but I do not understand how to 'code it'.
I have tried to create an endpoint C to serve the csrf token and then on the frontend add the token into the correct header for accessing another endpoint X with the antiforgery validation enabled but unfortunately I get 400 bad request.
In C#, Startup.cs
public override void ConfigureServices(IServiceCollection services)
{
...
services.AddControllersWithViews();
// Configure Anti-Forgery services
services.AddAntiforgery(options =>
{
options.HeaderName = "X-CSRF-TOKEN"; // Custom header name for the token
});
...
}
Controller.cs
[HttpGet("csrf-token")]
[AllowAnonymous]
public IActionResult GetCsrfToken()
{
// Retrieve the CSRF token from the session or create a new one
var tokens = _antiForgery.GetTokens(HttpContext);
Response.Cookies.Append("CSRF-TOKEN", tokens.RequestToken, new CookieOptions
{
HttpOnly = false, // Allow JS to access the cookie
Secure = true, // Ensure it's sent over HTTPS
SameSite = SameSiteMode.Strict // Protect against cross-site attacks
});
return Ok();
}
[HttpPost("submit-data")]
[ValidateAntiForgeryToken] // If removed it works
public IActionResult CreateResource()
{
return Ok();
}
main.js
import './assets/main.css'
import { createApp } from 'vue'
import App from './App.vue'
import axios from 'axios';
// Function to get the CSRF token from the cookie
function getCsrfTokenFromCookie() {
const name = "CSRF-TOKEN=";
const decodedCookie = decodeURIComponent(document.cookie);
const ca = decodedCookie.split(';');
for (let i = 0; i < ca.length; i++) {
let c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
}
}
return "";
}
// Example of making a POST request
async function sendData() {
try {
const response = await axios.post('https://localhost:5001/authenticate/submit-data');
console.log('Response:', response.data);
} catch (error) {
console.error('Error posting data:', error);
}
}
// Fetch CSRF token from the backend
async function fetchCsrfToken() {
try {
await axios.get('https://localhost:5001/authenticate/csrf-token');
} catch (error) {
console.error('Error fetching CSRF token:', error);
}
}
// Call this function when the app is initialized or after user login
fetchCsrfToken();
axios.defaults.headers.common['X-CSRF-TOKEN'] = getCsrfTokenFromCookie();
sendData();
createApp(App).mount('#app')
After executing the web-app I get a 400 Bad-Request caused by the antiforgery system in the backend, by removing the [ValidateAntiForgeryToken] directive I get 200 response.