From 734953f89bd19192540452d9e0fbb225d01b28c3 Mon Sep 17 00:00:00 2001 From: Don Isaac Date: Thu, 10 Oct 2024 06:19:07 -0400 Subject: [PATCH 1/4] fix: violations of upcoming `eslint/no-else-return` oxlint rule (#921) --- playground-authjs/server/api/auth/[...].ts | 11 ++++---- src/runtime/composables/commonAuthState.ts | 6 ++-- src/runtime/composables/local/useAuth.ts | 9 ++---- src/runtime/middleware/auth.ts | 28 +++++++++---------- src/runtime/plugins/refresh-token.server.ts | 4 +-- .../server/services/authjs/nuxtAuthHandler.ts | 8 ++---- 6 files changed, 27 insertions(+), 39 deletions(-) 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 cd4ff21c..1b311dfc 100644 --- a/src/runtime/composables/local/useAuth.ts +++ b/src/runtime/composables/local/useAuth.ts @@ -152,9 +152,7 @@ async function getSession(getSessionOptions?: GetSessionOptions): Promise { // @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) { + if (typeof metaAuth === 'object' && metaAuth.navigateUnauthenticatedTo) { return navigateTo(metaAuth.navigateUnauthenticatedTo) } - else { - 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 - } - }) + if (typeof globalAppMiddleware === 'object' && globalAppMiddleware.addDefaultCallbackUrl) { + let redirectUrl: string = to.fullPath + if (typeof globalAppMiddleware.addDefaultCallbackUrl === 'string') { + redirectUrl = globalAppMiddleware.addDefaultCallbackUrl } - return navigateTo(authConfig.provider.pages.login) + + return navigateTo({ + path: authConfig.provider.pages.login, + query: { + redirect: redirectUrl + } + }) } + 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 */ From 1aa5e1786c6c16883c7a039f2a173700e9fcf7f5 Mon Sep 17 00:00:00 2001 From: Marsel Shayhin <18054980+phoenix-ru@users.noreply.github.com> Date: Thu, 17 Oct 2024 18:12:40 +0200 Subject: [PATCH 2/4] fix(#926): correct and clarify Guest Mode (#929) --- .../application-side/protecting-pages.md | 8 +- src/runtime/middleware/auth.ts | 98 +++++++++++++------ 2 files changed, 75 insertions(+), 31 deletions(-) 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/src/runtime/middleware/auth.ts b/src/runtime/middleware/auth.ts index 48a3bcd3..b1cb4992 100644 --- a/src/runtime/middleware/auth.ts +++ b/src/runtime/middleware/auth.ts @@ -1,16 +1,15 @@ import type { navigateToAuthPages } from '../utils/url' import { determineCallbackUrl } from '../utils/url' +import { isProduction } from '../helpers' import { defineNuxtRouteMiddleware, navigateTo, useAuth, useRuntimeConfig } from '#imports' type MiddlewareMeta = boolean | { /** - * Whether to only allow unauthenticated users to access this page. + * Whether to allow only unauthenticated users to access this page. * * Authenticated users will be redirected to `/` or the route defined in `navigateAuthenticatedTo` - * - * @default undefined */ - unauthenticatedOnly?: boolean + unauthenticatedOnly: boolean /** * Where to redirect authenticated users if `unauthenticatedOnly` is set to true * @@ -38,41 +37,34 @@ declare module 'vue-router' { } export default defineNuxtRouteMiddleware((to) => { - 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,9 +93,13 @@ 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 } - if (typeof metaAuth === 'object' && metaAuth.navigateUnauthenticatedTo) { - return navigateTo(metaAuth.navigateUnauthenticatedTo) + + // Redirect path was provided + if (options.navigateUnauthenticatedTo) { + return navigateTo(options.navigateUnauthenticatedTo) } + + // Default callback URL was provided if (typeof globalAppMiddleware === 'object' && globalAppMiddleware.addDefaultCallbackUrl) { let redirectUrl: string = to.fullPath if (typeof globalAppMiddleware.addDefaultCallbackUrl === 'string') { @@ -117,5 +113,51 @@ export default defineNuxtRouteMiddleware((to) => { } }) } + + // Fall back to login page return navigateTo(authConfig.provider.pages.login) }) + +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 + } + } +} From a4b2b2e0cbf9a2bc9cd76988972672d3e85f429a Mon Sep 17 00:00:00 2001 From: Zoey Date: Thu, 17 Oct 2024 19:48:37 +0200 Subject: [PATCH 3/4] release: 0.9.4 (#930) --- docs/.vitepress/routes/navbar.ts | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/.vitepress/routes/navbar.ts b/docs/.vitepress/routes/navbar.ts index 84fd95cf..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.3', + text: '0.9.4', items: [ { text: '0.8.2', diff --git a/package.json b/package.json index 7152c00f..811df390 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@sidebase/nuxt-auth", - "version": "0.9.3", + "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!", From 47e619222073561833ffc81e85259de081b2b4bc Mon Sep 17 00:00:00 2001 From: Felix Ranesberger <52704891+felixranesberger@users.noreply.github.com> Date: Tue, 5 Nov 2024 17:53:05 +0100 Subject: [PATCH 4/4] docs(fix): use correct process env variable for baseUrl (#940) --- docs/guide/advanced/deployment/vercel.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guide/advanced/deployment/vercel.md b/docs/guide/advanced/deployment/vercel.md index 9ee92a21..744e8dc8 100644 --- a/docs/guide/advanced/deployment/vercel.md +++ b/docs/guide/advanced/deployment/vercel.md @@ -12,7 +12,7 @@ This variable is avalible at both build and run-time. Therefore you can referenc export default defineNuxtConfig({ modules: ['@sidebase/nuxt-auth'], auth: { - baseURL: process.env.VERCEL_URL ? `https://${VERCEL_URL}/api/auth` : undefined + baseURL: process.env.VERCEL_URL ? `https://${process.env.VERCEL_URL}/api/auth` : undefined } }) ```