Il modulo Nuxtjs Auth non funziona nel middleware

Oct 20 2020

Ciao, ho trovato una vecchia domanda simile alla mia senza risposta su StackOverFlow: nuxtjs / auth axios non invia cookie

Anche qui su GitHub, senza una valida soluzione: https://github.com/nuxt-community/auth-module/issues/478

Quindi il problema è che se chiamo $auth.loggedInin qualsiasi pagina, funziona come un incantesimo, ma se lo faccio nel mio middleware di autenticazione personalizzato (o se utilizzo il authmiddleware predefinito ), ritorna sempre false.

la mia configurazione di autenticazione in 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: '/',
      },
    },
  },

il mio middleware di autenticazione personalizzato

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('/')
  }
}

MODIFICARE:

Come richiesto, questo è il mio 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"
  }
}

Risposte

1 phips28 Nov 07 2020 at 16:13

ha avuto lo stesso problema e l'ho risolto ora con molte prove ed errori.

Il lato server non era a conoscenza dello stato di accesso, perché non lo implementava (?).

Quindi ho creato il mio middleware che imposta lo stato per il lato server.

Crea: 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;

quindi in nuxt.config.tsho questo middleware:

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

e questa mia configurazione di autenticazione:

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
      },
    },
  },

Quindi il nodejs / auth-middleware lato server ottiene lo stato di accesso + utente corretto (il mio token JWT include ID utente, email, nome, ambito: []).

1 FabioMagarelli Oct 20 2020 at 14:56

Sfortunatamente non sono stato in grado di nuxtjs/authlavorare nel middleware ma sono stato in grado di risolvere il problema utilizzando cookie-universal-nuxtin combinazione con nuxtjs/auth:

Puoi lasciare la tua versione di axios così com'è, non è necessario eseguire il downgrade per questa soluzione

  1. npm install --save cookie-universal-nuxt
  2. aggiungi cookie-universal-nuxtnel tuo nuxt.config.jsfile:
modules: [
    // other modules ...
    '@nuxtjs/auth',
    'cookie-universal-nuxt',
  ],
  1. creare un authmiddleware personalizzato . Ho chiamato il mio auth-usernella cartella 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. quindi dichiara il tuo middleware nella pagina principale della tua applicazione che desideri sia accessibile solo da utenti autenticati:
<script>
export default {
  middleware: ['auth-user'],
}
</script>

Se questo non funziona, controlla il nome del cookie in cui sono salvate le tue credenziali utente aprendo gli strumenti di sviluppo / ispettore nel browser.