Módulo Nuxtjs Auth não funciona no middleware

Oct 20 2020

Olá, encontrei uma pergunta antiga semelhante à minha sem resposta no StackOverFlow: nuxtjs / auth axios not send cookie

Também aqui no GitHub, sem uma solução válida: https://github.com/nuxt-community/auth-module/issues/478

Portanto, o problema é que se eu chamar $auth.loggedInqualquer página, funciona perfeitamente, mas se eu fizer isso no meu middleware de autenticação customizado (ou se eu usar o authmiddleware padrão ), ele sempre retorna false.

minha configuração de autenticação em nuxt.config.js

auth: {
    strategies: {
      local: {
        endpoints: {
          login: {
            url: '/rest-auth/login/',
            method: 'post',
            propertyName: 'key',
          },
          logout: { url: '/rest-auth/logout/', method: 'post' },
          user: {
            url: '/rest-auth/user/',
            method: 'get',
            propertyName: false,
          },
        },
        tokenType: 'Token',
        tokenName: 'Authorization',
      },
      redirect: {
        login: '/user_dashboard',
        home: '/',
      },
    },
  },

meu middleware de autenticação personalizado

export default async function ({ $auth, redirect }) {
  const user = await $auth.loggedIn
  console.log(user) // <-- this always return false for some reason :(
  if (user) {
    // let the user see the page
  } else {
    // redirect to homepage
    redirect('/')
  }
}

EDITAR:

Conforme solicitado, este é meu package.json:

{
  "name": "<MY_APP_NAME>",
  "version": "1.0.0",
  "private": true,
  "scripts": {
    "dev": "nuxt",
    "build": "nuxt build",
    "start": "nuxt start",
    "generate": "nuxt generate",
    "lint:js": "eslint --ext .js,.vue --ignore-path .gitignore .",
    "lint:style": "stylelint **/*.{vue,css} --ignore-path .gitignore",
    "lint": "npm run lint:js && npm run lint:style",
    "test": "jest"
  },
  "lint-staged": {
    "*.{js,vue}": "eslint",
    "*.{css,vue}": "stylelint"
  },
  "husky": {
    "hooks": {
      "commit-msg": "commitlint -E HUSKY_GIT_PARAMS",
      "pre-commit": "lint-staged"
    }
  },
  "dependencies": {
    "@nuxt/content": "^1.9.0",
    "@nuxtjs/auth": "^4.9.1",
    "@nuxtjs/axios": "^5.12.2",
    "@nuxtjs/pwa": "^3.0.2",
    "cookie-universal-nuxt": "^2.1.4",
    "core-js": "^3.6.5",
    "nuxt": "^2.14.7",
    "nuxt-buefy": "^0.4.3"
  },
  "devDependencies": {
    "@commitlint/cli": "^11.0.0",
    "@commitlint/config-conventional": "^11.0.0",
    "@nuxtjs/eslint-config": "^3.1.0",
    "@nuxtjs/eslint-module": "^3.0.0",
    "@nuxtjs/style-resources": "^1.0.0",
    "@nuxtjs/stylelint-module": "^4.0.0",
    "@vue/test-utils": "^1.1.0",
    "babel-core": "7.0.0-bridge.0",
    "babel-eslint": "^10.1.0",
    "babel-jest": "^26.5.0",
    "eslint": "^7.10.0",
    "eslint-config-prettier": "^6.12.0",
    "eslint-plugin-nuxt": "^1.0.0",
    "eslint-plugin-prettier": "^3.1.4",
    "husky": "^4.3.0",
    "jest": "^26.5.0",
    "lint-staged": "^10.4.0",
    "node-sass": "^4.14.1",
    "prettier": "^2.1.2",
    "sass-loader": "^10.0.3",
    "stylelint": "^13.7.2",
    "stylelint-config-prettier": "^8.0.2",
    "stylelint-config-standard": "^20.0.0",
    "vue-jest": "^3.0.4"
  }
}

Respostas

1 phips28 Nov 07 2020 at 16:13

tive o mesmo problema e resolvi-o agora com muitas tentativas e erros.

O lado do servidor não tinha conhecimento do estado de logado porque não o implementou (?).

Portanto, criei meu próprio middleware que define o estado do servidor.

Crie: middleware / auth-ssr.ts

import { Context, Middleware } from '@nuxt/types';
import { parse as parseCookie } from 'cookie';
import jsonwebtoken from 'jsonwebtoken';
import { IJwtPayload } from '../../api/_types/types';

/**
 * This middleware is needed when running with SSR
 * it checks if the token in cookie is set and injects it into the nuxtjs/auth module
 * otherwise it will redirect to login
 * @param context
 */
const debugAuthMiddleware: Middleware = async (context: Context) => {
  if (process.server && context.req.headers.cookie != null) {
    try {
      const cookies = parseCookie(context.req.headers.cookie);
      const token = cookies['auth._token.local'] || '';
      const tokenWithoutBearer = token.replace('Bearer ', '');
      // console.log('headers.cookie token', token);
      // console.log('debugAuthMiddleware $auth 1', context.$auth.$state); if (!token || token.includes('false')) { // sometimes it stores 'Bearer false' when it unsets return; } const jwt: IJwtPayload = (jsonwebtoken.decode(tokenWithoutBearer) as unknown) as IJwtPayload; // console.log('jwt payload', jwt); if (!jwt) { return; } // console.log('set token ✅', jwt); await context.$auth.setToken('locale', tokenWithoutBearer);
      await context.$auth.setUser(jwt); context.$auth.$state.loggedIn = true; } catch (e) { console.error('debugAuthMiddleware', e); } // console.log('debugAuthMiddleware $auth 2', context.$auth.$state);
  }
};

export default debugAuthMiddleware;

em seguida nuxt.config.ts, tenho este middleware:

router: {
    middleware: ['user-agent', 'auth-ssr', 'auth'],
},

e esta minha configuração de autenticação:

auth: {
    redirect: {
      logout: '/?signedOut=1',
      home: '/dashboard',
    },
    strategies: {
      local: {
        endpoints: {
          login: { url: '/api/v1/auth/login', method: 'post', propertyName: 'token' },
          logout: { url: '/api/v1/auth/logout', method: 'post' },
          user: { url: '/api/v1/user', method: 'get', propertyName: 'user' },
        },
        autoFetchUser: false, // do not fetch automatically! user object is coming from login api call
        rewriteRedirects: true, // If enabled, user will redirect back to the original guarded route instead of redirect.home.
        fullPathRedirect: true, // If true, use the full route path with query parameters for redirect
      },
    },
  },

Em seguida, o nodejs / auth-middleware do lado do servidor obtém o estado logado correto + usuário (meu token JWT inclui userId, email, nome, escopo: []).

1 FabioMagarelli Oct 20 2020 at 14:56

Infelizmente, não consegui fazer o nuxtjs/authtrabalho no middleware, mas consegui resolver o problema usando cookie-universal-nuxtem combinação com nuxtjs/auth:

Você pode deixar sua versão do Axios como está, sem necessidade de fazer downgrade para esta solução

  1. npm install --save cookie-universal-nuxt
  2. adicione cookie-universal-nuxtem seu nuxt.config.jsarquivo:
modules: [
    // other modules ...
    '@nuxtjs/auth',
    'cookie-universal-nuxt',
  ],
  1. crie um authmiddleware personalizado . Chamei o meu auth-userna pasta de middleware:
export default async function ({ app, redirect }) {
  // the following look directly for the cookie created by nuxtjs/auth
  // instead of using $auth.loggedIn const user = await app.$cookies.get('auth._token.local')
  if (user) {
    // let the user see the page
  } else {
    // redirect to homepage
    redirect('/')
  }
}
  1. em seguida, declare seu middleware na página raiz de seu aplicativo que você deseja que seja acessível apenas por usuários autenticados:
<script>
export default {
  middleware: ['auth-user'],
}
</script>

Se isso não funcionar, verifique o nome do cookie onde suas credenciais de usuário são salvas abrindo as ferramentas / inspetor do desenvolvedor no navegador.