5

Im looking to use $auth inside my Nuxt project, specially inside an axios plugin.

Here is my code:

plugins/api.js

export default function ({ $axios }, inject) {
  const api = $axios.create({
    headers: {
      common: {
        Accept: 'text/plain, */*',
      },
    },
  })

  // Set baseURL to something different
  api.setBaseURL('http://localhost:4100/')

  // Inject to context as $api
  inject('api', api)
}

Now the problem comes when I try to use $auth from @nuxtjs/auth-next package.

As stated in the docs:

This module globally injects $auth instance, meaning that you can access it anywhere using this.$auth. For plugins, asyncData, fetch, nuxtServerInit and Middleware, you can access it from context.$auth.

I tried the following:

  1. This results in $auth being undefined

    export default function ({ $axios, $auth }, inject) {

  2. This one was near

    export default function ({ $axios, app }, inject) { console.log(app) //This one logs $auth in the object logged console.log(app.$auth) // I don't understand why but this one returns undefined

My main goal here is to make use of this.$auth.strategy.token.get()and pass it (if the token exists of course) to the headers of every request made using this.$api

I have been looking for similar questions and answers but none has helped me to solve this, I could just add the token every time I write this.$api but that would increase the code unnecessarily.

Thanks in advance to all the people for your time and help.

EDIT:

Okay, now I made a test. and the next code is actually logging the $auth object correctly, it seems some time is needed to make it work but now Im afraid that using setTimeout could cause an error because I can't know exactly how much time is needed for $auth to be available.

export default function ({ $axios, app }, inject) {
  setTimeout(() => {
    console.log('After timeout', app.$auth)
  }, 50)

EDIT 2:

So now I have made more tests, and using 0 milliseconds instead of 50 works too, so I will use setTimeout with 0 milliseconds for now, I hope anyone find a better solution or explain why $auth is not available before using setTimeout so I can decide what to do with my code.

EDIT 3:

After trying to wrap all my previous code inside setTimeout I noticed that the code fails, so that isn't a solution.

Herii
  • 422
  • 5
  • 23
  • Try `store.$auth` – kissu Jul 08 '21 at 20:52
  • @kissu thanks for your reply. I have tried it and its undefined, when I log store it is showing that is has the $auth property but when I try to access it, it is undefined. So it's the same problem again. – Herii Jul 08 '21 at 20:56

2 Answers2

10

I have found a solution so I will post it so that every person that could have the same problem in the future can solve it.

It turns out that I could easily solve it using interceptors.

export default function ({ $axios, app }, inject) {
  // At this point app.$auth is undefined. (Unless you use setTimeout but that is not a solution)

  //Create axios instance
  const api = $axios.create({
    headers: {
      common: {
        Accept: 'application/json', //accept json
      },
    },
  })
  // Here is the magic, onRequest is an interceptor, so every request made will go trough this, and then we try to access app.$auth inside it, it is defined
  api.onRequest((config) => {
    // Here we check if user is logged in
    if (app.$auth.loggedIn) {
      // If the user is logged in we can now get the token, we get something like `Bearer yourTokenJ9F0JFODJ` but we only need the string without the word **Bearer**, So we split the string using the space as a separator and we access the second position of the array **[1]**

      const token = app.$auth.strategy.token.get().split(' ')[1]
      api.setToken(token, 'Bearer') // Here we specify the token and now it works!!
    }
  })

  // Set baseURL to something different
  api.setBaseURL('http://localhost:4100/')

  // Inject to context as $api
  inject('api', api)
}
Herii
  • 422
  • 5
  • 23
  • 1
    This was extremely helpful thank you! I ran into some issues, but also I managed to do this without having to inject a new instance. Using the `this.$axios` from my VueX frontend store code worked. I also had to make sure that my plugin was client-side by naming it with `.client.js` instead of just `.js`. And that the plugin was listed in both nuxt's top level plugins config AND in the `auth.plugins` array in the nuxt.config file. – EdgeCaseBerg Sep 16 '21 at 14:41
0

Also Nuxt Auth itself has provided a solution for this issue: https://auth.nuxtjs.org/recipes/extend/

Javaddev
  • 128
  • 6