Nuxt CookieStorage example - authenticated calls on the server do not work
See original GitHub issueSteps to reproduce
- Create a universal nuxt app -
yarn create nuxt-app
- Follow setup steps to add v2 feathers-vuex code - and Nuxt specific steps (i.e. cookie storage, nuxtServerInit/initAuth)
- Create a page
e.g. /test
and in thefetch()
function (called server side) place a call which requires auth:
<script>
import { models } from 'feathers-vuex';
export default {
async fetch ({ store, params }) {
const { User } = models.api;
const res = await User.get(1);
// Fails. Same call on the client will work.
}
}
</script>
- In a browser, set a valid
jwt
cookie, visit/test
and refresh
Expected behavior
The api call in fetch
should be made on the server authenticated and succeed.
Actual behavior
A NotAuthenticated
error is thrown.
Notes
nuxtServerInit/initAuth
is successful in reading thejwt
from the cookie and setting it in the store (i.e. state.auth.accessToken is valid)- but, it doesn’t seem to be used in subsequent api requests made on the server?
In trying to investigate this more, I found that the authenticate action when called on the server also fails:
dispatch('auth/authenticate'); // throws an error - No accessToken found in storage
If the accessToken from the store is passed, this gets further but then bails with a document not defined error.
nuxtServerInit({ commit, dispatch, state }, { req }) {
return initAuth({
commit,
dispatch,
req,
moduleName: 'auth',
cookieName: COOKIE_ACCESS_TOKEN
}).then(() => {
dispatch('auth/authenticate', { accessToken: state.auth.accessToken, strategy: 'jwt' })
});
// throws an error - document is not defined . Same if `feathersClient` is passed to `initAuth()`
The document is not defined
error is thrown in cookie-storage.js, since setAccessToken()
is called when feathersClient.authenticate()
succeeds.
// cookie-storage.js
value: function _setCookie(value) {
document.cookie = value;
}
Which obviously will fail on the server.
I am new to feathers-vuex and trying to evaluate it for use in a project. I’ve spent a decent amount of time looking through old cases/examples on this topic but cannot seem to find anything definitive which covers this scenario?
Thanks in advance!
Issue Analytics
- State:
- Created 4 years ago
- Reactions:2
- Comments:8 (2 by maintainers)
Top GitHub Comments
I managed to fix this by tweaking the examples in the docs and studying the internals a bit more. Docs are fine for a Nuxt app in SPA mode, i.e. auth/service calls on the client, but you’ll hit problems in universal mode when trying to authenticate the user on the server. This is basically because of the recommendation to use CookieStorage as the auth storage adapter.
TL;DR - if you want a Nuxt/SSR/feathers-vuex setup where you can authenticate the user on the server and make authenticated calls in
fetch/asyncData
, the example below might be a useful starting point.Case can be closed - there’s no bug here, tho perhaps covering universal setup/gotchas in the docs would be nice! Thanks for hard work on this library.
Tweaks for Nuxt universal mode app (auth on the server):
auth/authenticate
needs to be called somewhere afterinitAuth()
. I added this innuxtServerInit()
- but it could go elsewhere, i.e. middleware. With the MemoryStorage adapter being used on the server,auth/authenticate
doesn’t throw thedocument is not defined
error anymore.Example:
For anyone who is reading this later, I found a short chat going on featherjs slack and a response from marshall that confirms it that doing auth on SSR has problems currently:
just checking here for a sanity check. We just found that calling auth/authenticate inside nuxtServerInit whilst nuxt is in production mode will cause the nuxt SSR to cache the response or something, then issuing users with incorrect JWTs. (thankfully we caught this before it got to production)
So I think that the best solution is going for client side auth for now.