Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Axios CSRF header configuration doesn't work #40

Open
Mado13 opened this issue Mar 14, 2025 · 2 comments
Open

Axios CSRF header configuration doesn't work #40

Mado13 opened this issue Mar 14, 2025 · 2 comments

Comments

@Mado13
Copy link

Mado13 commented Mar 14, 2025

Description

When using Inertia.js with Phoenix, setting axios.defaults.xsrfHeaderName doesn't affect the CSRF header sent with Inertia requests.

Problem

According to the documentation, setting axios.defaults.xsrfHeaderName = "x-csrf-token" should configure Axios to send the CSRF token with the header name that Phoenix expects. However, Inertia continues to send the token as x-xsrf-token instead, causing Phoenix's CSRF protection to reject the requests

Reproduction Steps

Configure Axios in app.js:

import axios from "axios";
axios.defaults.xsrfHeaderName = "x-csrf-token";

Initialize Inertia app as normal
Submit a form using Inertia's useForm to a Phoenix endpoint
Observe in the network tab that the request includes x-xsrf-token header but not x-csrf-token

Expected Behavior

The CSRF token should be sent with the x-csrf-token header as configured in the Axios defaults.

Actual Behavior

The CSRF token is sent with the x-xsrf-token header regardless of the Axios configuration.

Workaround

I was able to work around this issue by intercepting Inertia's requests and manually changing the header:

Inertia.on('before', (event) => {
  const getCookieValue = (name) => {
    const cookies = document.cookie.split('; ');
    for (const cookie of cookies) {
      const [cookieName, cookieValue] = cookie.split('=');
      if (cookieName === name) {
        return decodeURIComponent(cookieValue);
      }
    }
    return null;
  };

  const token = getCookieValue('XSRF-TOKEN');
  
  if (token) {
    event.detail.visit.headers['x-csrf-token'] = token;
    delete event.detail.visit.headers['x-xsrf-token'];
  }
});

Environment

Inertia.js: 2.3.0
Phoenix: 1.7.0
Svelte: 5

@derrickreimer
Copy link
Collaborator

Hmm that's odd! This is not what I'm seeing in my applications using the Axios defaults overrides (though I'm typically using React and not Svelte). Can you share a bit more of your app.js setup?

@Mado13
Copy link
Author

Mado13 commented Mar 18, 2025

Yeah sure this is it!

import axios from "axios";
import { createInertiaApp } from "@inertiajs/svelte";
import { Inertia } from "@inertiajs/inertia";
import { mount, hydrate } from "svelte";
import { register, init, getLocaleFromNavigator, locale } from 'svelte-i18n';
import "phoenix_html";
import { setupPWA } from "./pwa-setup";
import '../styles/global.scss';
import Layout from './Layout.svelte'

// Initialize application state
window.pwa = {};
window.isPWAInstalled = false;

// Configure i18n (internationalization)
const setupI18n = () => {
  // Register language packs
  register('en', () => import('../lang/en.json'));
  register('he', () => import('../lang/he.json'));
  
  // Initialize with browser's preferred language, with a fallback
  init({
    fallbackLocale: 'he',
    initialLocale: 'he',
  });

  locale.subscribe((lang) => {
    console.log(`Setting language to ${lang}, direction: ${lang === 'he' ? 'rtl' : 'ltr'}`);
    document.documentElement.dir = lang === 'he' ? 'rtl' : 'ltr';
    document.documentElement.lang = lang;
  });
  
  return new Promise((resolve) => {
    const unsubscribe = locale.subscribe((lang) => {
      if (lang) {
        document.documentElement.dir = lang === 'he' ? 'rtl' : 'ltr';
        document.documentElement.lang = lang;
        unsubscribe();
        resolve();
      }
    });
    
    setTimeout(() => {
      locale.set('he');
    }, 100);
  });
};

// Configure HTTP requests
const configureAxios = () => {
  axios.defaults.xsrfHeaderName = "x-csrf-token";
  
  // Add CSRF token to Inertia requests
  Inertia.on('before', (event) => {
    const token = getCookieValue('XSRF-TOKEN');
    
    if (token) {
      event.detail.visit.headers['x-csrf-token'] = token;
      delete event.detail.visit.headers['x-xsrf-token']; // Remove incorrect header
    }
  });
};

const getCookieValue = (name) => {
  const cookies = document.cookie.split('; ');
  for (const cookie of cookies) {
    const [cookieName, cookieValue] = cookie.split('=');
    if (cookieName === name) {
      return decodeURIComponent(cookieValue);
    }
  }
  return null;
};

// Initialize Inertia application
const initApp = () => {
  createInertiaApp({
    // Resolve page components
    resolve: name => {
      const pages = import.meta.glob('./Pages/**/*.svelte', { eager: true })
      let page = pages[`./Pages/${name}.svelte`]
      return { default: page.default, layout: page.layout || Layout }
    },
    
    // Mount the application
    setup({ el, App, props }) {
      const enhancedProps = {
        ...props,
        pwaInstalled: window.isPWAInstalled ?? false,
      };
      
      // Use hydration for server-rendered content, otherwise mount
      if (el.dataset.serverRendered === 'true') {
        hydrate(App, { target: el, props: enhancedProps });
      } else {
        mount(App, { target: el, props: enhancedProps });
      }
    },
  });
};

// Application bootstrap
const bootstrap = async () => {
  await setupI18n();
  configureAxios();
  initApp();
  setupPWA();
};

// Start the application
bootstrap().catch(err => console.error('Bootstrap error:', err));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants