diff --git a/docs/.vitepress/routes/navbar.ts b/docs/.vitepress/routes/navbar.ts
index 0fd9c64b..052865df 100644
--- a/docs/.vitepress/routes/navbar.ts
+++ b/docs/.vitepress/routes/navbar.ts
@@ -44,7 +44,7 @@ export const routes: DefaultTheme.Config['nav'] = [
],
},
{
- text: '0.9.2',
+ text: '0.9.4',
items: [
{
text: '0.8.2',
diff --git a/docs/.vitepress/theme/components/Layout.vue b/docs/.vitepress/theme/components/Layout.vue
index e726d834..01c12b21 100644
--- a/docs/.vitepress/theme/components/Layout.vue
+++ b/docs/.vitepress/theme/components/Layout.vue
@@ -6,6 +6,7 @@ import Banner from './Banner.vue'
const { Layout } = DefaultTheme
// Banner Configuration
+const isBannerEnabled = false
const bannerConfig = {
// Leave text empty to disable the banner
text: '🚀 NuxtAuth v0.9.0 has been released!',
@@ -22,7 +23,7 @@ const bannerConfig = {
-
+
diff --git a/docs/guide/application-side/protecting-pages.md b/docs/guide/application-side/protecting-pages.md
index 8d8a7c5e..0df29fd0 100644
--- a/docs/guide/application-side/protecting-pages.md
+++ b/docs/guide/application-side/protecting-pages.md
@@ -78,10 +78,12 @@ definePageMeta({
#### `unauthenticatedOnly`
-Whether to only allow unauthenticated users to access this page. Authenticated users will be redirected to / or the route defined in `navigateAuthenticatedTo`.
+Whether to allow only unauthenticated users to access this page. Authenticated users will be redirected to `/` or to the route specified in `navigateAuthenticatedTo`.
-:::tip
-Setting `unauthenticatedOnly: false` is equivalent to setting `auth: false` from the user perspective, but requires some extra middleware steps, so it is a bit less efficient. Therefore it is recommended to use `auth: false` instead.
+If you want to let everyone see the page, set `auth: false` instead (see [Local Middleware](#local-middleware)).
+
+:::warning
+This option is required from `0.9.4` onwards to prevent ambiguity ([related issue](https://github.com/sidebase/nuxt-auth/issues/926)). Make sure you set it, otherwise [Guest Mode](#guest-mode) will be **enabled** by default — your guests would be able to see the page, but your authenticated users would be redirected away.
:::
#### `navigateAuthenticatedTo`
diff --git a/package.json b/package.json
index ed686c44..811df390 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@sidebase/nuxt-auth",
- "version": "0.9.2",
+ "version": "0.9.4",
"license": "MIT",
"type": "module",
"description": "Authentication built for Nuxt 3! Easily add authentication via OAuth providers, credentials or Email Magic URLs!",
diff --git a/playground-authjs/server/api/auth/[...].ts b/playground-authjs/server/api/auth/[...].ts
index d310edee..eccec0c7 100644
--- a/playground-authjs/server/api/auth/[...].ts
+++ b/playground-authjs/server/api/auth/[...].ts
@@ -35,14 +35,13 @@ export default NuxtAuthHandler({
// Any object returned will be saved in `user` property of the JWT
return user
}
- else {
- console.error('Warning: Malicious login attempt registered, bad credentials provided')
- // If you return null then an error will be displayed advising the user to check their details.
- return null
+ console.error('Warning: Malicious login attempt registered, bad credentials provided')
- // You can also Reject this callback with an Error thus the user will be sent to the error page with the error message as a query parameter
- }
+ // If you return null then an error will be displayed advising the user to check their details.
+ return null
+
+ // You can also Reject this callback with an Error thus the user will be sent to the error page with the error message as a query parameter
}
})
]
diff --git a/src/runtime/composables/commonAuthState.ts b/src/runtime/composables/commonAuthState.ts
index 08b2a006..19c53d67 100644
--- a/src/runtime/composables/commonAuthState.ts
+++ b/src/runtime/composables/commonAuthState.ts
@@ -24,12 +24,10 @@ export function makeCommonAuthState() {
if (loading.value) {
return 'loading'
}
- else if (data.value) {
+ if (data.value) {
return 'authenticated'
}
- else {
- return 'unauthenticated'
- }
+ return 'unauthenticated'
})
// Determine base url of app
diff --git a/src/runtime/composables/local/useAuth.ts b/src/runtime/composables/local/useAuth.ts
index 23d1832b..1e77dcf0 100644
--- a/src/runtime/composables/local/useAuth.ts
+++ b/src/runtime/composables/local/useAuth.ts
@@ -164,9 +164,7 @@ async function getSession(getSessionOptions?: GetSessionOptions): Promise {
- const metaAuth = typeof to.meta.auth === 'object'
- ? {
- unauthenticatedOnly: true,
- ...to.meta.auth
- }
- : to.meta.auth
-
- if (metaAuth === false) {
+ // Normalize options. If `undefined` was returned, we need to skip middleware
+ const options = normalizeUserOptions(to.meta.auth)
+ if (!options) {
return
}
const authConfig = useRuntimeConfig().public.auth
const { status, signIn } = useAuth()
- const isGuestMode = typeof metaAuth === 'object' && metaAuth.unauthenticatedOnly
- // Guest mode happy path 1: Unauthenticated user is allowed to view page
+
+ // Guest Mode - only unauthenticated users are allowed
+ const isGuestMode = options.unauthenticatedOnly
+ const isAuthenticated = status.value === 'authenticated'
if (isGuestMode && status.value === 'unauthenticated') {
+ // Guest Mode - unauthenticated users can stay on the page
return
}
-
- // Guest mode edge-case: Developer used guest-mode config style but set `unauthenticatedOnly` to `false`
- if (typeof metaAuth === 'object' && !metaAuth.unauthenticatedOnly) {
- return
+ else if (isGuestMode && isAuthenticated) {
+ // Guest Mode - authenticated users should be redirected to another page
+ return navigateTo(options.navigateAuthenticatedTo)
}
-
- if (status.value === 'authenticated') {
- // Guest mode happy path 2: Authenticated user should be directed to another page
- if (isGuestMode) {
- return navigateTo(metaAuth.navigateAuthenticatedTo ?? '/')
- }
+ else if (isAuthenticated) {
+ // Authenticated users don't need any further redirects
return
}
// We do not want to block the login page when the local provider is used
- if (authConfig.provider?.type === 'local') {
- const loginRoute: string | undefined = authConfig.provider?.pages?.login
+ if (authConfig.provider.type === 'local') {
+ const loginRoute: string | undefined = authConfig.provider.pages.login
if (loginRoute && loginRoute === to.path) {
return
}
@@ -101,23 +93,71 @@ export default defineNuxtRouteMiddleware((to) => {
// @ts-ignore This is valid for a backend-type of `authjs`, where sign-in accepts a provider as a first argument
return signIn(undefined, signInOptions) as ReturnType
}
- else if (typeof metaAuth === 'object' && metaAuth.navigateUnauthenticatedTo) {
- return navigateTo(metaAuth.navigateUnauthenticatedTo)
+
+ // Redirect path was provided
+ if (options.navigateUnauthenticatedTo) {
+ return navigateTo(options.navigateUnauthenticatedTo)
}
- else {
- if (typeof globalAppMiddleware === 'object' && globalAppMiddleware.addDefaultCallbackUrl) {
- let redirectUrl: string = to.fullPath
- if (typeof globalAppMiddleware.addDefaultCallbackUrl === 'string') {
- redirectUrl = globalAppMiddleware.addDefaultCallbackUrl
+
+ // Default callback URL was provided
+ if (typeof globalAppMiddleware === 'object' && globalAppMiddleware.addDefaultCallbackUrl) {
+ let redirectUrl: string = to.fullPath
+ if (typeof globalAppMiddleware.addDefaultCallbackUrl === 'string') {
+ redirectUrl = globalAppMiddleware.addDefaultCallbackUrl
+ }
+
+ return navigateTo({
+ path: authConfig.provider.pages.login,
+ query: {
+ redirect: redirectUrl
}
+ })
+ }
+
+ // Fall back to login page
+ return navigateTo(authConfig.provider.pages.login)
+})
- return navigateTo({
- path: authConfig.provider.pages.login,
- query: {
- redirect: redirectUrl
+interface MiddlewareOptionsNormalized {
+ unauthenticatedOnly: boolean
+ navigateAuthenticatedTo: string
+ navigateUnauthenticatedTo?: string
+}
+
+/**
+ * @returns `undefined` is returned when passed options are `false`
+ */
+function normalizeUserOptions(userOptions: MiddlewareMeta | undefined): MiddlewareOptionsNormalized | undefined {
+ // false - do not use middleware
+ // true - use defaults
+ if (typeof userOptions === 'boolean' || userOptions === undefined) {
+ return userOptions !== false
+ ? {
+ // Guest Mode off if `auth: true`
+ unauthenticatedOnly: false,
+ navigateAuthenticatedTo: '/',
+ navigateUnauthenticatedTo: undefined
}
- })
+ : undefined
+ }
+
+ // We check in runtime in case usage error was not caught by TS
+ if (typeof userOptions === 'object') {
+ // Guest Mode on to preserve compatibility. A warning is also issued to prevent unwanted behaviour
+ if (userOptions.unauthenticatedOnly === undefined) {
+ if (!isProduction) {
+ console.warn(
+ '[@sidebase/nuxt-auth] `unauthenticatedOnly` was not provided to `definePageMeta` - defaulting to Guest Mode enabled. '
+ + 'Read more at https://auth.sidebase.io/guide/application-side/protecting-pages#middleware-options'
+ )
+ }
+ userOptions.unauthenticatedOnly = true
+ }
+
+ return {
+ unauthenticatedOnly: userOptions.unauthenticatedOnly,
+ navigateAuthenticatedTo: userOptions.navigateAuthenticatedTo ?? '/',
+ navigateUnauthenticatedTo: userOptions.navigateUnauthenticatedTo
}
- return navigateTo(authConfig.provider.pages.login)
}
-})
+}
diff --git a/src/runtime/plugins/refresh-token.server.ts b/src/runtime/plugins/refresh-token.server.ts
index bd79d432..1d05065d 100644
--- a/src/runtime/plugins/refresh-token.server.ts
+++ b/src/runtime/plugins/refresh-token.server.ts
@@ -63,9 +63,7 @@ export default defineNuxtPlugin({
)
return
}
- else {
- rawRefreshToken.value = extractedRefreshToken
- }
+ rawRefreshToken.value = extractedRefreshToken
}
rawToken.value = extractedToken
diff --git a/src/runtime/server/services/authjs/nuxtAuthHandler.ts b/src/runtime/server/services/authjs/nuxtAuthHandler.ts
index ee6baa18..82e845a6 100644
--- a/src/runtime/server/services/authjs/nuxtAuthHandler.ts
+++ b/src/runtime/server/services/authjs/nuxtAuthHandler.ts
@@ -253,12 +253,10 @@ function getRequestBaseFromH3Event(event: H3Event, trustHost: boolean): string {
return `${protocol}://${host}`
}
- else {
- // This may throw, we don't catch it
- const origin = getServerOrigin(event)
+ // This may throw, we don't catch it
+ const origin = getServerOrigin(event)
- return origin
- }
+ return origin
}
/** Actions supported by auth handler */