N
Nuxt10mo ago
NT Diesel

nav guard and redirection

have problem with my nuxt3 app i am making middle ware like this
import { useMainStore } from "~/stores/main";

export default defineNuxtRouteMiddleware(async (to, from) => {
if (process.server) return;

const MainStore = useMainStore();

if (!MainStore.AccessToken) {
return navigateTo("/auth/login");
}
const config = useRuntimeConfig();
try {
const resp = await $fetch(`${config.public.serverApi}/login`, {
method: "post",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
body: {
fromRefresh: true,
},
});
MainStore.Login(resp.username, resp.accessToken);
return;
} catch (e) {
console.log(e.data.message);
return navigateTo("/auth/login");
}
});
import { useMainStore } from "~/stores/main";

export default defineNuxtRouteMiddleware(async (to, from) => {
if (process.server) return;

const MainStore = useMainStore();

if (!MainStore.AccessToken) {
return navigateTo("/auth/login");
}
const config = useRuntimeConfig();
try {
const resp = await $fetch(`${config.public.serverApi}/login`, {
method: "post",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
body: {
fromRefresh: true,
},
});
MainStore.Login(resp.username, resp.accessToken);
return;
} catch (e) {
console.log(e.data.message);
return navigateTo("/auth/login");
}
});
and i have the default layout like this
<script setup></script>

<template>
<div class="relative min-h-[100dvh]">
<!-- start of bg of the auth pages -->
<div class="absolute h-full w-full">
<img src="/imgs/auth-bg.jpg" class="w-full h-full object-cover" />
<div class="w-full h-full absolute bg-primary/30 inset-0"></div>
<img
src="/imgs/logo.png"
class="absolute top-2 left-2 w-[15%] object-cover aspect-square"
/>
</div>
<!-- end of bg of the auth pages -->
<slot />
</div>
</template>

<style scoped></style>
<script setup></script>

<template>
<div class="relative min-h-[100dvh]">
<!-- start of bg of the auth pages -->
<div class="absolute h-full w-full">
<img src="/imgs/auth-bg.jpg" class="w-full h-full object-cover" />
<div class="w-full h-full absolute bg-primary/30 inset-0"></div>
<img
src="/imgs/logo.png"
class="absolute top-2 left-2 w-[15%] object-cover aspect-square"
/>
</div>
<!-- end of bg of the auth pages -->
<slot />
</div>
</template>

<style scoped></style>
and i have the index page like this
<script setup>
definePageMeta({
middleware: ["require-auth"],
// or middleware: 'auth'
});
</script>

<template>
<div></div>
</template>
<script setup>
definePageMeta({
middleware: ["require-auth"],
// or middleware: 'auth'
});
</script>

<template>
<div></div>
</template>
1 Reply
NT Diesel
NT DieselOP10mo ago
and i have the page called /auth/login like this
<script setup>
import { useMainStore } from "~/stores/main";
const MainStore = useMainStore();
const toast = useToast();
const state = reactive({
username: undefined,
password: undefined,
});
const ShowPassword = ref(false);
const Loading = ref(false);

async function onSubmit(event) {
const Config = useRuntimeConfig();
if (Loading.value) return;
Loading.value = true;
try {
const response = await $fetch(`${Config.public.serverApi}/login`, {
method: "post",
credentials: "include",
body: {
username: event.data.username,
password: event.data.password,
},
});
MainStore.Login(event.data.username, response.accessToken);
toast.add({
icon: "i-heroicons-check-badge",
description: "Logged In Successfully Redirecting To Home Page",
title: "Success",
timeout: 5000,
color: "green",
callback: () => {
navigateTo("/");
},
});
} catch (e) {
toast.add({
icon: "ic:baseline-sms-failed",
description: e.data.message,
title: "Failed ...",
color: "red",
timeout: 5000,
});
} finally {
Loading.value = false;
}
}
</script>
<script setup>
import { useMainStore } from "~/stores/main";
const MainStore = useMainStore();
const toast = useToast();
const state = reactive({
username: undefined,
password: undefined,
});
const ShowPassword = ref(false);
const Loading = ref(false);

async function onSubmit(event) {
const Config = useRuntimeConfig();
if (Loading.value) return;
Loading.value = true;
try {
const response = await $fetch(`${Config.public.serverApi}/login`, {
method: "post",
credentials: "include",
body: {
username: event.data.username,
password: event.data.password,
},
});
MainStore.Login(event.data.username, response.accessToken);
toast.add({
icon: "i-heroicons-check-badge",
description: "Logged In Successfully Redirecting To Home Page",
title: "Success",
timeout: 5000,
color: "green",
callback: () => {
navigateTo("/");
},
});
} catch (e) {
toast.add({
icon: "ic:baseline-sms-failed",
description: e.data.message,
title: "Failed ...",
color: "red",
timeout: 5000,
});
} finally {
Loading.value = false;
}
}
</script>
<template>
<div
class="bg-neutral-800/50 w-[40%] min-h-[60%] z-20 absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 flex flex-col items-center justify-center rounded-md gap-8"
>
<h3>Login</h3>
<UForm
:validate="validate"
:state="state"
class="flex flex-col items-center justify-center gap-4 w-full"
@submit="onSubmit"
>
<UFormGroup label="Username" name="username" class="w-[80%]">
<UInput v-model="state.username" />
</UFormGroup>

<UFormGroup label="Password" name="password" class="w-[80%]">
<UInput
v-model="state.password"
:type="ShowPassword ? 'text' : 'password'"
:ui="{ icon: { trailing: { pointer: '' } } }"
>
<template #trailing>
<UButton
v-show="state.password && state.password != ''"
color="gray"
variant="link"
icon="ph:eye-light"
:padded="false"
@click="ShowPassword = !ShowPassword"
/>
</template>
</UInput>
</UFormGroup>

<UButton size="xl" type="submit" :lodaing="Loading">
Login
</UButton>
</UForm>
<p class="flex items-center small-text">
Don't have account ?
<UButton
color="primary"
variant="link"
to="/auth/register"
class="small-text"
>
Create New One
</UButton>
</p>
</div>
</template>
<template>
<div
class="bg-neutral-800/50 w-[40%] min-h-[60%] z-20 absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 flex flex-col items-center justify-center rounded-md gap-8"
>
<h3>Login</h3>
<UForm
:validate="validate"
:state="state"
class="flex flex-col items-center justify-center gap-4 w-full"
@submit="onSubmit"
>
<UFormGroup label="Username" name="username" class="w-[80%]">
<UInput v-model="state.username" />
</UFormGroup>

<UFormGroup label="Password" name="password" class="w-[80%]">
<UInput
v-model="state.password"
:type="ShowPassword ? 'text' : 'password'"
:ui="{ icon: { trailing: { pointer: '' } } }"
>
<template #trailing>
<UButton
v-show="state.password && state.password != ''"
color="gray"
variant="link"
icon="ph:eye-light"
:padded="false"
@click="ShowPassword = !ShowPassword"
/>
</template>
</UInput>
</UFormGroup>

<UButton size="xl" type="submit" :lodaing="Loading">
Login
</UButton>
</UForm>
<p class="flex items-center small-text">
Don't have account ?
<UButton
color="primary"
variant="link"
to="/auth/register"
class="small-text"
>
Create New One
</UButton>
</p>
</div>
</template>
with the middle ware above applied to it but when the navigation guard redirect me to the /auth/login all the page style got broken and gives me err hydration missmatch on the console it only works fine if i make my /auth/login page as ClientOnly page and if u will ask why i am making the middle ware only on client its bec the /login route of backend uses cookies which isnt availible for nuxt server it only availble on client browser if i make the middle ware on both client and server this problem wil be solver but the backend server will always return back with 401 or 400 bec the cookies wil be empty and doesnt contain the jwt may be force name the layout ?
Want results from more Discord servers?
Add your server