Nuxtjs Auth module not working in the middleware
Solution 1
had the same problem, and I solved it now with a lot of trial & error.
The server side had no knowledge of the loggedIn state, because they did not implement it(?).
So I created my own middleware that sets the state for the server side.
Create: 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;
then in nuxt.config.ts
I have this middleware:
router: {
middleware: ['user-agent', 'auth-ssr', 'auth'],
},
and this my auth config:
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
},
},
},
Then the server side nodejs/auth-middleware gets the correct loggedIn state + user (my JWT token includes userId, email, name, scope: []).
Solution 2
Unfortunately I wasn't able to make nuxtjs/auth
work in the middleware but I was able to solve the issue by using cookie-universal-nuxt
in combination with nuxtjs/auth
:
You can leave your axios version as it is, no need to downgrade for this solution
npm install --save cookie-universal-nuxt
- add
cookie-universal-nuxt
in yournuxt.config.js
file:
modules: [
// other modules ...
'@nuxtjs/auth',
'cookie-universal-nuxt',
],
- create a custom
auth
middleware. I called mineauth-user
in the middleware folder:
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('/')
}
}
- then declare your middleware in the root page of your application that you want to be accessible only by authenticated users:
<script>
export default {
middleware: ['auth-user'],
}
</script>
If this doesn't work, check the cookie name where your user credential are saved by opening the developer tools / inspector in the browser.
Related videos on Youtube
Fabio Magarelli
I'm a software developer with experience in Healthcare and Research. I like working remotely most of the time but also have the opportunity to meet my team in the office (wherever that may be). I am eager to learn and have no problem stepping out of my comfort zone in order to achieve my goals.
Updated on June 04, 2022Comments
-
Fabio Magarelli almost 2 years
Hi I found an old question similar to mine with no answer on StackOverFlow : nuxtjs/auth axios not sending cookie
Also here on GitHub, without a valid solution: https://github.com/nuxt-community/auth-module/issues/478
So the problem is that if I call
$auth.loggedIn
in any page, it works like a charm but if I do it in my custom authentication middleware (or if I use the defaultauth
middleware), it always returnfalse
.my auth configuration 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: '/', }, }, },
my custom auth middleware
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('/') } }
EDIT:
As requested, this is my 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" } }
-
nathan1658 over 3 yearsHi seems I’ve solved the case by downgrade the nuxt/axios module, can you share your package.json? Maybe I can have a look on mine and compare it.
-
Fabio Magarelli over 3 years@nathan1658 sure, see edit on the question
-
Fabio Magarelli over 3 years@nathan1658 following your suggestion, I found this issue: github.com/nuxt-community/auth-module/issues/853 so I'm trying downgrading axios with:
npm install @nuxtjs/[email protected]
. wish me luck. -
Fabio Magarelli over 3 yearsstill not working
-
nathan1658 over 3 yearsHi sorry for late reply, I have the same version with yours. Can you check the secure setting on the cookie i.e. set it to false when debugging on http?
-
-
Fabio Magarelli over 3 yearsThis seems a lot of work but probably is a more proper way of solving the issue. good job!
-
phips28 over 3 yearsImo this should be implemented directly within nuxtjs/auth to male this work out of the box for SSR. Maybe I have time in the future to propose a PR. Or someone else sees this and implements it ;)
-
Iman Shafiei almost 3 yearsSharing codes and examples would always be helpful.