1

I'm trying to find a solution for 3 days now and I didn't find anything related to my problem. I have a Nuxt.js frontend that uses the auth module to get a JWT token from a DRF backend.

After login, the server prints out this:

Forbidden (CSRF cookie not set.): /api/accounts/login/
[04/Jun/2021 10:36:44] "POST /api/accounts/login/ HTTP/1.1" 403 2870

In the network tab, I can see this in the request headers when I try to log in: X-CSRFToken: csrftoken, which means that the csrf token is not passed properly. Right?

In my nuxt.config.js file, I have these settings:

axios: {
    baseURL: 'http://localhost:8000',
    headers: {
      "X-CSRFToken": "csrftoken",
    },
    xsrfCookieName: "csrftoken",
    xsrfHeaderName: "X-CSRFToken",
  },

  // authentication module configuration
  auth: {
    strategies: {
      local: {
        endpoints: {
          login: {
            url: '/api/accounts/login/',
            method: 'post',
            propertyName: 'access',
            altProperty: 'refresh'
          },
          logout: {},
          user: false
        }
      }
    },
    redirect: {
      login: '/login',
    },
  },
  router: {
    middleware: ['auth']
  },
  ...
}

Here is my login script:

export default {
  data() {
    return {
      user: {
        username: "",
        password: "",
      },
    };
  },
  methods: {
    async login() {
      try {
        await this.$auth.loginWith("local", {
          data: this.user,
        });
        console.log("VALID");
      } catch (err) {
        console.log("INVALID");
      }
    },
  },
};

How can I pass the csrf token properly to my Django backend?

kissu
  • 40,416
  • 14
  • 65
  • 133
  • Can you give us an example of what it should look like? Because here, you do setup it as `"X-CSRFToken": "csrftoken"` and it is sending what it should, no? – kissu Jun 04 '21 at 09:00

2 Answers2

1

Looking at the axios configuration here: https://github.com/axios/axios#global-axios-defaults

You can see how to setup a default header with something like this instance.defaults.headers.common['Authorization'] = AUTH_TOKEN;

Then, in Nuxt, you can extend the default auth plugin: https://auth.nuxtjs.org/recipes/extend

nuxt.config.js

auth: {
  ...
  plugins: [{ src: '~/plugins/nuxt-auth.js', mode: 'client' }],
},

And set your CSRF token there with an env variable.

!!!
This is a bit tricky but the plugins above is nested in the auth key, not in the global scope of the nuxt config file.
!!!

/plugins/nuxt-auth.js

export default ({ $axios, $config: { csrfToken } }) => {
  $axios.defaults.headers.common['X-CSRFToken'] = csrfToken;
}

PS: if you need some help on how to use env variables in Nuxt, you can check this question: How to use .env variables in Nuxt?

kissu
  • 40,416
  • 14
  • 65
  • 133
0

I got it to work by obtaining the csrf token via JavaScript, just like in the Django docs:

~/assets/scripts/cookie.js

export function getCookie(name) {
    let cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        const cookies = document.cookie.split(';');
        for (let i = 0; i < cookies.length; i++) {
            const cookie = cookies[i].trim();
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}

Then I used it inside the plugin script:

~/plugins/nuxt-auth.js

import { getCookie } from '../assets/scripts/cookie.js'

export default ({ $axios }) => {
    $axios.defaults.headers.common['X-CSRFToken'] = getCookie('csrftoken');
}

I edited the nuxt.config.js file like this:

auth: {
  ...
  plugins: [{ src: '~/plugins/nuxt-auth.js', mode: 'client' }],
  ...
},

Now the X-CSRFToken in the header is correct:

X-CSRFToken: LWs(...)nm9