N
Nuxt3mo ago
Spctr

Frontend middleware auth with backend auth

hello all, I'm tryin to create an auth system for my webpage My problem is that I can't log in. When I can I can't use $store.user.value it's null most of the time. my userStore
// stores/userStore.ts
import { ref } from 'vue';

export const useUserStore = () => {
const user = useState('user', () => {
if (process.client) {
const storedUser = localStorage.getItem('user');
return storedUser ? JSON.parse(storedUser) : null;
}
return null;
});

const setUser = (newUser) => {
user.value = newUser;
if (newUser && process.client) {
localStorage.setItem('user', JSON.stringify(newUser));
} else {
if (process.client) {
localStorage.removeItem('user');
}
}
};

const clearUser = () => {
user.value = null;
if (process.client) {
localStorage.removeItem('user');
}
};

return { user, setUser, clearUser };
};
// stores/userStore.ts
import { ref } from 'vue';

export const useUserStore = () => {
const user = useState('user', () => {
if (process.client) {
const storedUser = localStorage.getItem('user');
return storedUser ? JSON.parse(storedUser) : null;
}
return null;
});

const setUser = (newUser) => {
user.value = newUser;
if (newUser && process.client) {
localStorage.setItem('user', JSON.stringify(newUser));
} else {
if (process.client) {
localStorage.removeItem('user');
}
}
};

const clearUser = () => {
user.value = null;
if (process.client) {
localStorage.removeItem('user');
}
};

return { user, setUser, clearUser };
};
my storePlugin
// ~/plugins/storePlugin.ts
import {useUserStore} from "~/stores/userStore";

export default defineNuxtPlugin((nuxtApp) => {
const userStore = useUserStore();

if (process.client) {
const storedUser = localStorage.getItem('user');
if (storedUser) {
userStore.setUser(JSON.parse(storedUser));
}
}

nuxtApp.provide('store', {
user: userStore.user,
setUser: userStore.setUser,
clearUser: userStore.clearUser,
});
});
// ~/plugins/storePlugin.ts
import {useUserStore} from "~/stores/userStore";

export default defineNuxtPlugin((nuxtApp) => {
const userStore = useUserStore();

if (process.client) {
const storedUser = localStorage.getItem('user');
if (storedUser) {
userStore.setUser(JSON.parse(storedUser));
}
}

nuxtApp.provide('store', {
user: userStore.user,
setUser: userStore.setUser,
clearUser: userStore.clearUser,
});
});
and my middleware
import { Middleware } from '@nuxt/types'
import axios from 'axios';
import {useUserStore} from "~/stores/userStore";


const protectedRouteNames = [
{
name: 'index',
isLoginRequired: false,
requiredRole: []
},
{
name: 'dashboard',
isLoginRequired: true,
requiredRole: []
},
{
name: 'admin-user-management',
isLoginRequired: true,
requiredRole: ['admin']
},
]

function getRouteProtectionInfo(routeName: string | any) {
return protectedRouteNames.find(obj => obj.name === routeName);
}

async function isUserAuthenticated(): Promise<any> {
const { user, setUser } = useUserStore();
if (user.value) {
return { user: user.value };
}

try {
const response = await axios.get("http://localhost:4000/api/auth/verify", { withCredentials: true });
user.value = response.data.user;
return { user: response.data.user };
} catch (error) {
return { user: null };
}
}

export default defineNuxtRouteMiddleware(async (to, from) => {
const routeProtectionInfo = getRouteProtectionInfo(to.name);
const { user, setUser } = useUserStore();

if (routeProtectionInfo) {
if (routeProtectionInfo.isLoginRequired) {
const userAuthData = await isUserAuthenticated();
console.log('User: ', user)

if (userAuthData && userAuthData.user) {
setUser(userAuthData.user);
console.log('User: ', user)

const userRole = userAuthData.user.role;

if (routeProtectionInfo.requiredRole.length > 0 && !routeProtectionInfo.requiredRole.includes(userRole)) {
return navigateTo('/unauthorized');
}
} else {
console.log("User is not authenticated");
return navigateTo('/');
}
}
}
});
import { Middleware } from '@nuxt/types'
import axios from 'axios';
import {useUserStore} from "~/stores/userStore";


const protectedRouteNames = [
{
name: 'index',
isLoginRequired: false,
requiredRole: []
},
{
name: 'dashboard',
isLoginRequired: true,
requiredRole: []
},
{
name: 'admin-user-management',
isLoginRequired: true,
requiredRole: ['admin']
},
]

function getRouteProtectionInfo(routeName: string | any) {
return protectedRouteNames.find(obj => obj.name === routeName);
}

async function isUserAuthenticated(): Promise<any> {
const { user, setUser } = useUserStore();
if (user.value) {
return { user: user.value };
}

try {
const response = await axios.get("http://localhost:4000/api/auth/verify", { withCredentials: true });
user.value = response.data.user;
return { user: response.data.user };
} catch (error) {
return { user: null };
}
}

export default defineNuxtRouteMiddleware(async (to, from) => {
const routeProtectionInfo = getRouteProtectionInfo(to.name);
const { user, setUser } = useUserStore();

if (routeProtectionInfo) {
if (routeProtectionInfo.isLoginRequired) {
const userAuthData = await isUserAuthenticated();
console.log('User: ', user)

if (userAuthData && userAuthData.user) {
setUser(userAuthData.user);
console.log('User: ', user)

const userRole = userAuthData.user.role;

if (routeProtectionInfo.requiredRole.length > 0 && !routeProtectionInfo.requiredRole.includes(userRole)) {
return navigateTo('/unauthorized');
}
} else {
console.log("User is not authenticated");
return navigateTo('/');
}
}
}
});
The funny thing is that I can go on pages which are not listed in protectedRouteNames
7 Replies
Spctr
SpctrOP3mo ago
If u need to see something just tell me i've tried to fix it .. can someone help why does the user wont be stored has someone an idea or a hint
RicharDVD
RicharDVD3mo ago
I believe your solution would only work client side. I would make the plugin a client only plugin and the route middleware only run on the client (by checking import.meta.server and early returning). See if that helps you any further
Spctr
SpctrOP3mo ago
where should I do this checks
RicharDVD
RicharDVD3mo ago
For the plugin you can just rename the file to [filename].client.ts and for the middleware:
export default defineNuxtRouteMiddleware(() => {
if (import.meta.server) {
return;
}

...
}
export default defineNuxtRouteMiddleware(() => {
if (import.meta.server) {
return;
}

...
}
Spctr
SpctrOP3mo ago
holy .. that works for me thank u just this small changes
RicharDVD
RicharDVD3mo ago
Happy to help😃
Spctr
SpctrOP3mo ago
thank u so much
Want results from more Discord servers?
Add your server