diff --git a/src/runtime/composables/local/useAuth.ts b/src/runtime/composables/local/useAuth.ts index 1368fe0d..0d688b70 100644 --- a/src/runtime/composables/local/useAuth.ts +++ b/src/runtime/composables/local/useAuth.ts @@ -10,7 +10,7 @@ import { type UseAuthStateReturn, useAuthState } from './useAuthState' import { callWithNuxt } from '#app/nuxt' // @ts-expect-error - #auth not defined import type { SessionData } from '#auth' -import { navigateTo, nextTick, useNuxtApp, useRuntimeConfig } from '#imports' +import { navigateTo, nextTick, useCookie, useNuxtApp, useRuntimeConfig } from '#imports' type Credentials = { username?: string, email?: string, password?: string } & Record @@ -87,6 +87,28 @@ const signOut: SignOutFunc = async (signOutOptions) => { } } + // Explicitly clear both cookies to avoid watcher issues + // Use the same options to clear the cookie as the ones used to set it + useCookie(config.token.cookieName, { + maxAge: 0, + domain: config.token.cookieDomain, + sameSite: config.token.sameSiteAttribute, + secure: config.token.secureCookieAttribute, + httpOnly: config.token.httpOnlyCookieAttribute + }).value = null + + // Clear the refresh cookie too, if enabled + if (config.refresh.isEnabled) { + useCookie(config.refresh.token.cookieName, { + maxAge: 0, + domain: config.refresh.token.cookieDomain, + sameSite: config.refresh.token.sameSiteAttribute, + secure: config.refresh.token.secureCookieAttribute, + httpOnly: config.refresh.token.httpOnlyCookieAttribute + }).value = null + } + + // Clear local state data.value = null rawToken.value = null rawRefreshToken.value = null diff --git a/src/runtime/plugins/refresh-token.server.ts b/src/runtime/plugins/refresh-token.server.ts index bd79d432..c386f98b 100644 --- a/src/runtime/plugins/refresh-token.server.ts +++ b/src/runtime/plugins/refresh-token.server.ts @@ -11,7 +11,7 @@ export default defineNuxtPlugin({ const { rawToken, rawRefreshToken, refreshToken, token, lastRefreshedAt } = useAuthState() - if (refreshToken.value && token.value) { + if (refreshToken.value) { const config = nuxtApp.$config.public.auth const configToken = useTypedBackendConfig(useRuntimeConfig(), 'local') @@ -20,10 +20,12 @@ export default defineNuxtPlugin({ const { path, method } = provider.refresh.endpoint const refreshRequestTokenPointer = provider.refresh.token.refreshRequestTokenPointer - // include header in case of auth is required to avoid 403 rejection - const headers = new Headers({ - [configToken.token.headerName]: token.value - } as HeadersInit) + const headers = new Headers() + + // To perform the refresh, some backends may require the auth token to also be set. + if (token.value) { + headers.set(configToken.token.headerName, token.value) + } try { const response = await _fetch>(nuxtApp, path, { @@ -40,8 +42,7 @@ export default defineNuxtPlugin({ console.error( `Auth: string token expected, received instead: ${JSON.stringify( extractedToken - )}. Tried to find token at ${ - provider.token.signInResponseTokenPointer + )}. Tried to find token at ${provider.token.signInResponseTokenPointer } in ${JSON.stringify(response)}` ) return @@ -57,8 +58,7 @@ export default defineNuxtPlugin({ console.error( `Auth: string token expected, received instead: ${JSON.stringify( extractedRefreshToken - )}. Tried to find token at ${ - provider.refresh.token.signInResponseRefreshTokenPointer + )}. Tried to find token at ${provider.refresh.token.signInResponseRefreshTokenPointer } in ${JSON.stringify(response)}` ) return