Skip to content

Commit

Permalink
fix: fix infinite recursion when trying to do auth on error pages
Browse files Browse the repository at this point in the history
  • Loading branch information
phoenix-ru committed Nov 21, 2024
1 parent de5ca1f commit f3762b7
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 8 deletions.
2 changes: 1 addition & 1 deletion src/runtime/composables/authjs/useAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ function getProviders() {
*
* @param getSessionOptions - Options for getting the session, e.g., set `required: true` to enforce that a session _must_ exist, the user will be directed to a login page otherwise.
*/
async function getSession(getSessionOptions?: GetSessionOptions): Promise<SessionData> {
async function getSession(getSessionOptions?: GetSessionOptions): Promise<SessionData | null> {
const nuxt = useNuxtApp()

const callbackUrlFallback = await getRequestURLWN(nuxt)
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/middleware/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export default defineNuxtRouteMiddleware((to) => {
* We do not want to enforce protection on `404` pages (unless the user opts out of it by setting `allow404WithoutAuth: false`).
*
* This is to:
* - improve UX and DX: Having to log-in to see a `404` is not pleasent,
* - improve UX and DX: Having to log-in to see a `404` is not pleasant,
* - avoid the `Error [ERR_HTTP_HEADERS_SENT]`-error that occurs when we redirect to the sign-in page when the original to-page does not exist. Likely related to https://github.com/nuxt/framework/issues/9438
*
*/
Expand Down
21 changes: 18 additions & 3 deletions src/runtime/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { getHeader } from 'h3'
import authMiddleware from './middleware/auth'
import { getNitroRouteRules } from './utils/kit'
import { _refreshHandler, addRouteMiddleware, defineNuxtPlugin, useAuth, useAuthState, useRuntimeConfig } from '#imports'
import { FetchConfigurationError } from './utils/fetch'

Check failure on line 5 in src/runtime/plugin.ts

View workflow job for this annotation

GitHub Actions / test-module

`./utils/fetch` import should occur before import of `#imports`

export default defineNuxtPlugin(async (nuxtApp) => {
// 1. Initialize authentication state, potentially fetch current session
Expand All @@ -10,6 +11,7 @@ export default defineNuxtPlugin(async (nuxtApp) => {

// use runtimeConfig
const runtimeConfig = useRuntimeConfig().public.auth
const globalAppMiddleware = runtimeConfig.globalAppMiddleware

const routeRules = import.meta.server ? getNitroRouteRules(nuxtApp._route.path) : {}

Expand All @@ -30,8 +32,22 @@ export default defineNuxtPlugin(async (nuxtApp) => {
}

// Only fetch session if it was not yet initialized server-side
if (typeof data.value === 'undefined' && !nitroPrerender && !disableServerSideAuth) {
await getSession()
const isErrorUrl = nuxtApp.ssrContext?.error === true
const requireAuthOnErrorPage = globalAppMiddleware === true || (typeof globalAppMiddleware === 'object' && globalAppMiddleware.allow404WithoutAuth)
const shouldFetchSession = typeof data.value === 'undefined'
&& !nitroPrerender
&& !disableServerSideAuth
&& !(isErrorUrl && requireAuthOnErrorPage)

if (shouldFetchSession) {
try {
await getSession()
} catch (e) {

Check failure on line 45 in src/runtime/plugin.ts

View workflow job for this annotation

GitHub Actions / test-module

Closing curly brace appears on the same line as the subsequent block
// Do not throw the configuration error as it can lead to infinite recursion
if (!(e instanceof FetchConfigurationError)) {
throw e
}
}
}

// 2. Setup session maintanence, e.g., auto refreshing or refreshing on foux
Expand All @@ -55,7 +71,6 @@ export default defineNuxtPlugin(async (nuxtApp) => {
}

// 3. Enable the middleware, either globally or as a named `auth` option
const { globalAppMiddleware } = useRuntimeConfig().public.auth
if (
globalAppMiddleware === true
|| (typeof globalAppMiddleware === 'object' && globalAppMiddleware.isEnabled)
Expand Down
21 changes: 18 additions & 3 deletions src/runtime/utils/fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,38 @@ import { resolveApiUrlPath } from './url'
import { callWithNuxt, useRuntimeConfig } from '#app'
import type { useNuxtApp } from '#imports'

const ERROR_PREFIX = '[@sidebase/nuxt-auth]'

export async function _fetch<T>(nuxt: ReturnType<typeof useNuxtApp>, path: string, fetchOptions?: Parameters<typeof $fetch>[1]): Promise<T> {
const runtimeConfig = await callWithNuxt(nuxt, useRuntimeConfig)
const joinedPath = resolveApiUrlPath(path, runtimeConfig)

// Prevent callback recursion when doing internal routing
if (runtimeConfig.public.auth.disableInternalRouting === false) {
const currentPath = nuxt.ssrContext?.event?.path
// const isErrorUrl = nuxt.ssrContext?.error &&

Check failure on line 14 in src/runtime/utils/fetch.ts

View workflow job for this annotation

GitHub Actions / test-module

Trailing spaces not allowed
if (currentPath?.startsWith(joinedPath)) {
console.error(`${ERROR_PREFIX} Recursion detected at ${joinedPath}. Have you set the correct \`auth.baseURL\`?`)
throw new FetchConfigurationError('Server configuration error')
}
}

try {
return $fetch(joinedPath, fetchOptions)
}
catch (error) {
let errorMessage = `[@sidebase/nuxt-auth] Error while requesting ${joinedPath}.`
let errorMessage = `${ERROR_PREFIX} Error while requesting ${joinedPath}.`
if (runtimeConfig.public.auth.provider.type === 'authjs') {
errorMessage += ' Have you added the authentication handler server-endpoint `[...].ts`? Have you added the authentication handler in a non-default location (default is `~/server/api/auth/[...].ts`) and not updated the module-setting `auth.basePath`?'
}
errorMessage += ' Error is:'
console.error(errorMessage)
console.error(error)

throw new Error(
'Runtime error, checkout the console logs to debug, open an issue at https://github.com/sidebase/nuxt-auth/issues/new/choose if you continue to have this problem'
throw new FetchConfigurationError(
'Runtime error, check the console logs to debug, open an issue at https://github.com/sidebase/nuxt-auth/issues/new/choose if you continue to have this problem'
)
}
}

export class FetchConfigurationError extends Error {}

0 comments on commit f3762b7

Please sign in to comment.