3

I am writing a headless solution for a WordPress website and noticed that for one particular endpoint, I need to authenticate to pull some data that will be used publicly. But, I'm concerned that where I'm using it will expose it to the web.

In my store/index.js I use the nuxtServerInit action method to execute some actions and I pass them some objects they need to fulfill their tasks:

async nuxtServerInit ({ dispatch }, { $axios, app }) {
  await dispatch('initialize', { $axios, app })
},

$axios is passed because it will be used to query the API, and app is passed to help build the options to authenticate the request.

Is this a security vulnerability in Nuxt SSR? I think it is. If so, where are the only valid areas you can use secrets? asyncData ()?

kissu
  • 40,416
  • 14
  • 65
  • 133
Jonathan
  • 10,936
  • 8
  • 64
  • 79

1 Answers1

4

If you're using SSR, you can use the privateRuntimeConfig runtime object and pass your secret in the nuxt.config.js file

export default {
  privateRuntimeConfig: {
    apiSecret: process.env.API_SECRET
  }
}

If you read the documentation of nuxtServerInit, you can see that

Vuex action that is called only on server-side to pre-populate the store

Since this method is server-side only, you can use apiSecret (in my example) and it should be totally fine security-wise.

PS: Keep in mind that everything beyond what is generated on the server (hence, with NodeJS or nuxtServerInit) is "public". So your VueJS's client code lifecycle hooks are public: mounted(), fetch(), asyncData() because they will be visible on your browser's devtools.


Also, should your endpoint be that critical? If so, nuxtServerInit is the good way to go. If you need to fetch some more data in a "private way", you'll need to proxy it through some backend to hide the sensitive info and retrieve only the useful public data.

kissu
  • 40,416
  • 14
  • 65
  • 133
  • Thanks @kissu. I was wondering if someone would notice that it seems contradictory to authenticate an endpoint if the data used will be exposed anyway. It's because I'm using a forms plugin and I want to pull the structure of my forms, and their API forces this to have authentication – Jonathan May 25 '21 at 13:39
  • 1
    Yep, there are some cases where this is needed. It was essentially to be sure that you're not over-protecting something that didn't needed it. But yeah, your solution is good here! – kissu May 25 '21 at 13:42
  • I did read about `nuxtServerInit` being run server-side but I just wanted to be certain. You know what it's like to deploy something and you question everything? :) I asked about `asyncData` because I believed it is also run server-side. The only thing you need to be careful of is that the object you return is safe for use client-side. So, you can use secrets in the method, as long as it doesn't return them? – Jonathan May 25 '21 at 13:42
  • 2
    The best way to be double sure of what is public is to open a new tab, open the network tab and load your app. Then, inspect all the calls made by your app. Since `nuxtServerInit` is SSR only, it will be generated and shipped to your browser (not fetched on your browser). So, you won't see any unsafe call (because it will be done ahead of time on the server). `asyncData` will be both `server` + `client`, so you cannot use it. The linked article about the runtime config can be helpful IMO. And, it is more of a: "which method is called server side only?" + your `privateRuntimeConfig` key combo. – kissu May 25 '21 at 13:49
  • Yeah, in experimentation now I'm seeing that asyncData is not on the server or at least, `process.server` is true when inside of it I think – Jonathan May 25 '21 at 13:58
  • 1
    I've linked your the lifecycle, here you can clearly see that `asyncData` is used both on `server` and `client`: https://nuxtjs.org/docs/2.x/concepts/nuxt-lifecycle – kissu May 25 '21 at 14:02