-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Session logic, login, update dependences
- Loading branch information
Showing
12 changed files
with
680 additions
and
302 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { createSharedComposable } from "@vueuse/core"; | ||
import type { Payload, SignPayload } from "~/types/useJwt"; | ||
|
||
const useJwt = createSharedComposable(() => { | ||
const extractJwtPayload = (token: string) => { | ||
const [ header, payload, signature ] = token.split('.'); | ||
const payloadData = JSON.parse(atob(payload)); | ||
|
||
return payloadData; | ||
} | ||
|
||
const extractTokenData = (token: string): Payload => { | ||
return extractJwtPayload(token); | ||
} | ||
|
||
const extractSignData = (token: string): SignPayload => { | ||
return extractJwtPayload(token); | ||
} | ||
|
||
return { | ||
extractTokenData, | ||
extractSignData, | ||
}; | ||
}); | ||
|
||
export default useJwt; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,36 @@ | ||
export default defineNuxtRouteMiddleware(() => { | ||
const { loggedIn } = useUserSession(); | ||
export default defineNuxtRouteMiddleware(async (middleware) => { | ||
const nuxtApp = useNuxtApp(); | ||
const localeRoute = useLocaleRoute(); | ||
const { loggedIn, fetch, session, clear } = useUserSession(); | ||
const { extractTokenData } = useJwt(); | ||
|
||
if (!loggedIn.value) { | ||
return navigateTo("/login"); | ||
// Si el usuario está logueado, comprueba si los tokens están expirados o necesitan ser renovados | ||
if (loggedIn.value) { | ||
const accessTokenData = extractTokenData(session.value.access_token); | ||
const refreshTokenData = extractTokenData(session.value.refresh_token); | ||
|
||
// Date.now() es en milisegundos y exp en segundos, | ||
// por eso se multiplica por 1000 | ||
const accessTokenIsExpired = Date.now() >= accessTokenData.exp * 1000; | ||
const refreshTokenIsExpired = Date.now() >= refreshTokenData.exp * 1000; | ||
|
||
const tokensAreExpired = accessTokenIsExpired && refreshTokenIsExpired; | ||
const tokensNeedRefresh = accessTokenIsExpired && !refreshTokenIsExpired; | ||
|
||
if (tokensAreExpired) { | ||
await clear(); | ||
} | ||
|
||
if (tokensNeedRefresh) { | ||
await fetch(); | ||
} | ||
} | ||
|
||
return null; | ||
// Si el usuario no está logueado, lo redirige al login | ||
if (!loggedIn.value) { | ||
const loginRoute = localeRoute('login', nuxtApp.$i18n.locale); | ||
const loginPath = loginRoute != null ? loginRoute.path : '/'; | ||
|
||
return navigateTo(loginPath); | ||
} | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import useJwt from "~/composables/useJwt"; | ||
import { LoginAndRefreshResponse } from "~/types/auth"; | ||
|
||
export default defineNitroPlugin(() => { | ||
const config = useRuntimeConfig(); | ||
const { extractTokenData } = useJwt(); | ||
|
||
// Se ejecuta al comprobar la sesión al usar SSR desde el composable (/api/_auth/session) | ||
// o al usar useUserSession().fetch() | ||
sessionHooks.hook('fetch', async (session, event) => { | ||
const accessTokenData = extractTokenData(session.access_token); | ||
const refreshTokenData = extractTokenData(session.refresh_token); | ||
|
||
// Date.now() es en milisegundos y exp en segundos, | ||
// por eso se multiplica por 1000 | ||
const accessTokenIsExpired = Date.now() >= accessTokenData.exp * 1000; | ||
const refreshTokenIsExpired = Date.now() >= refreshTokenData.exp * 1000; | ||
|
||
const tokensAreExpired = accessTokenIsExpired && refreshTokenIsExpired; | ||
const tokensNeedRefresh = accessTokenIsExpired && !refreshTokenIsExpired; | ||
|
||
// Si los tokens están expirados cerramos la sesión | ||
if (tokensAreExpired) { | ||
await clearUserSession(event); | ||
} | ||
|
||
// Si solo el token de acceso está expirado y el de refresco no, refrescamos los tokens | ||
if (tokensNeedRefresh) { | ||
try { | ||
const response = await $fetch<LoginAndRefreshResponse>(config.public.backendUrl + '/auth/refresh', { | ||
method: 'GET', | ||
headers: { | ||
Authorization: 'Bearer ' + session.refresh_token, | ||
}, | ||
}); | ||
|
||
await replaceUserSession(event, { | ||
user: { | ||
email: response.user.email, | ||
avatar: response.user.avatar, | ||
isAdmin: response.user.isAdmin, | ||
isVerified: response.user.isVerified, | ||
}, | ||
access_token: response.access_token, | ||
refresh_token: response.refresh_token, | ||
}, { | ||
maxAge: Number(config.nuxtSessionTime), | ||
}); | ||
} catch (error) { | ||
await clearUserSession(event); | ||
} | ||
} | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
export interface Payload { | ||
user_id: number; | ||
iat: number; | ||
exp: number; | ||
} | ||
|
||
export interface SignPayload { | ||
user_id: number; | ||
type: string; | ||
iat: number; | ||
exp: number; | ||
} |
Oops, something went wrong.