feat: add refresh token functionality to login page + redirect if already logged in

This commit is contained in:
mrjvs
2026-08-16 22:46:48 +02:00
parent 47d703f6fd
commit 268287749d
3 changed files with 85 additions and 1 deletions

View File

@@ -120,6 +120,12 @@ form.account.register {
column-gap: 24px;
margin-bottom: 48px;
}
form.account.loading {
display: flex;
align-items: center;
text-align: center;
justify-content: center;
}
form.account.register .h-captcha {
grid-column: 1 / span 2;

View File

@@ -0,0 +1,61 @@
import { FetchError } from 'ofetch';
import type { ApiAuthRefreshRequest } from '~~/shared/api-types';
export function useLogin() {
const authStore = useAuthStore();
const meStore = useMeStore();
async function handleRefresh(): Promise<{ hasNewTokens: boolean }> {
if (meStore.user) {
return { hasNewTokens: false }; // You're good, nothing to do
}
const tokens = authStore.getTokens();
if (!tokens || !tokens.refreshToken) {
return { hasNewTokens: false }; // No tokens to use
}
try {
const result = await $fetch('/api/auth/refresh', {
method: 'POST',
body: {
token: tokens?.refreshToken ?? ''
} satisfies ApiAuthRefreshRequest
});
authStore.set({
accessToken: result.accessToken,
refreshToken: result.refreshToken
});
return { hasNewTokens: true };
} catch (err) {
if (err instanceof FetchError) {
if (err.statusCode === 401) {
// Refresh token expired, log out
authStore.logout();
}
}
return { hasNewTokens: false };
}
}
function isLoggedIn() {
if (meStore.user) {
return true;
}
return false;
}
function canRefresh() {
const tokens = authStore.getTokens();
if (!tokens || !tokens.refreshToken) {
return false; // No refresh token to use
}
return true;
}
return {
handleRefresh,
canRefresh,
isLoggedIn
};
}

View File

@@ -14,6 +14,14 @@ const registerURI = computed(() => {
return `/account/register`;
});
const login = useLogin();
const { status } = useAsyncData(async () => {
const result = await login.handleRefresh();
if (result.hasNewTokens || login.isLoggedIn()) {
await authUtils.safelyRedirectAfterLogin(redirect.value);
}
}, { server: false });
const loginForm = reactive({ username: '', password: '' });
const { execute, isLoading } = useAsync({
@@ -42,7 +50,16 @@ const { execute, isLoading } = useAsync({
</script>
<template>
<div>
<div v-if="status !== 'success'">
<div class="account-form-wrapper">
<form
class="account loading"
>
<Loader />
</form>
</div>
</div>
<div v-else>
<div class="account-form-wrapper">
<form
class="account"