1

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.

1
  • Try to use F12 developer tools Application to check whether the "CSRF-TOKEN" cookie exist or not, and when you execute the sendData function, try to use F12 Network to check the request header, might be the "X-CSRF-TOKEN" is not add in the request header. Commented Jan 14 at 8:55

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.