fix: show login when session token expires

This commit is contained in:
ArielLeyva 2025-09-14 12:15:15 -04:00
parent 2f0c1f5fa2
commit 680f6da6fd
4 changed files with 38 additions and 9 deletions

View File

@ -7,9 +7,11 @@ export const useAuthStore = defineStore("auth", {
state: (): { state: (): {
user: IUser | null; user: IUser | null;
jwt: string; jwt: string;
logoutTimer: number | null;
} => ({ } => ({
user: null, user: null,
jwt: "", jwt: "",
logoutTimer: null,
}), }),
getters: { getters: {
// user and jwt getter removed, no longer needed // user and jwt getter removed, no longer needed
@ -37,5 +39,8 @@ export const useAuthStore = defineStore("auth", {
clearUser() { clearUser() {
this.$reset(); this.$reset();
}, },
setLogoutTimer(logoutTimer: number | null) {
this.logoutTimer = logoutTimer;
},
}, },
}); });

View File

@ -64,3 +64,8 @@ interface IRegexp {
} }
type UserTheme = "light" | "dark" | ""; type UserTheme = "light" | "dark" | "";
interface SessionToken {
token: string;
expiresAt: string;
}

View File

@ -5,17 +5,29 @@ import { jwtDecode } from "jwt-decode";
import { baseURL, noAuth } from "./constants"; import { baseURL, noAuth } from "./constants";
import { StatusError } from "@/api/utils"; import { StatusError } from "@/api/utils";
export function parseToken(token: string) { export function parseToken(body: SessionToken) {
// falsy or malformed jwt will throw InvalidTokenError // falsy or malformed jwt will throw InvalidTokenError
const data = jwtDecode<JwtPayload & { user: IUser }>(token); const data = jwtDecode<JwtPayload & { user: IUser }>(body.token);
document.cookie = `auth=${token}; Path=/; SameSite=Strict;`; document.cookie = `auth=${body.token}; Path=/; SameSite=Strict;`;
localStorage.setItem("jwt", token); localStorage.setItem("jwt", body.token);
const authStore = useAuthStore(); const authStore = useAuthStore();
authStore.jwt = token; authStore.jwt = body.token;
authStore.setUser(data.user); authStore.setUser(data.user);
const expiresAt = new Date(body.expiresAt);
if (authStore.logoutTimer) {
clearTimeout(authStore.logoutTimer);
}
authStore.setLogoutTimer(
window.setTimeout(() => {
logout();
}, expiresAt.getTime() - Date.now())
);
} }
export async function validateLogin() { export async function validateLogin() {
@ -44,11 +56,12 @@ export async function login(
body: JSON.stringify(data), body: JSON.stringify(data),
}); });
const body = await res.text();
if (res.status === 200) { if (res.status === 200) {
const body = await res.json();
parseToken(body); parseToken(body);
} else { } else {
const body = await res.text();
throw new StatusError( throw new StatusError(
body || `${res.status} ${res.statusText}`, body || `${res.status} ${res.statusText}`,
res.status res.status
@ -64,11 +77,12 @@ export async function renew(jwt: string) {
}, },
}); });
const body = await res.text();
if (res.status === 200) { if (res.status === 200) {
const body = await res.json();
parseToken(body); parseToken(body);
} else { } else {
const body = await res.text();
throw new StatusError( throw new StatusError(
body || `${res.status} ${res.statusText}`, body || `${res.status} ${res.statusText}`,
res.status res.status

View File

@ -214,8 +214,13 @@ func printToken(w http.ResponseWriter, _ *http.Request, d *data, user *users.Use
return http.StatusInternalServerError, err return http.StatusInternalServerError, err
} }
w.Header().Set("Content-Type", "text/plain") response := map[string]interface{}{
if _, err := w.Write([]byte(signed)); err != nil { "token": signed,
"expiresAt": claims.ExpiresAt.Time.Format(time.RFC3339), // fecha en string ISO 8601
}
w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(response); err != nil {
return http.StatusInternalServerError, err return http.StatusInternalServerError, err
} }
return 0, nil return 0, nil