Skip to content

Commit

Permalink
Merge branch 'main' into update-pull-request
Browse files Browse the repository at this point in the history
  • Loading branch information
Vijayabhaskar96 authored Oct 29, 2024
2 parents 75d167e + a4b2b2e commit 0f7e51a
Show file tree
Hide file tree
Showing 10 changed files with 103 additions and 70 deletions.
2 changes: 1 addition & 1 deletion docs/.vitepress/routes/navbar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export const routes: DefaultTheme.Config['nav'] = [
],
},
{
text: '0.9.2',
text: '0.9.4',
items: [
{
text: '0.8.2',
Expand Down
3 changes: 2 additions & 1 deletion docs/.vitepress/theme/components/Layout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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!',
Expand All @@ -22,7 +23,7 @@ const bannerConfig = {
<GithubStarsButton owner="sidebase" repo="nuxt-auth" />
</template>

<template #home-hero-before>
<template v-if="isBannerEnabled" #home-hero-before>
<Banner v-bind="bannerConfig" />
</template>
</Layout>
Expand Down
8 changes: 5 additions & 3 deletions docs/guide/application-side/protecting-pages.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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!",
Expand Down
11 changes: 5 additions & 6 deletions playground-authjs/server/api/auth/[...].ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
})
]
Expand Down
6 changes: 2 additions & 4 deletions src/runtime/composables/commonAuthState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,10 @@ export function makeCommonAuthState<SessionData>() {
if (loading.value) {
return 'loading'
}
else if (data.value) {
if (data.value) {
return 'authenticated'
}
else {
return 'unauthenticated'
}
return 'unauthenticated'
})

// Determine base url of app
Expand Down
9 changes: 3 additions & 6 deletions src/runtime/composables/local/useAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,7 @@ async function getSession(getSessionOptions?: GetSessionOptions): Promise<Sessio
if (onUnauthenticated) {
return onUnauthenticated()
}
else {
await navigateTo(callbackUrl ?? await getRequestURLWN(nuxt), { external })
}
await navigateTo(callbackUrl ?? await getRequestURLWN(nuxt), { external })
}

return data.value
Expand Down Expand Up @@ -232,9 +230,8 @@ async function refresh(getSessionOptions?: GetSessionOptions) {
)
return
}
else {
rawRefreshToken.value = extractedRefreshToken
}

rawRefreshToken.value = extractedRefreshToken
}

rawToken.value = extractedToken
Expand Down
120 changes: 80 additions & 40 deletions src/runtime/middleware/auth.ts
Original file line number Diff line number Diff line change
@@ -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
*
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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<typeof navigateToAuthPages>
}
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)
}
})
}
4 changes: 1 addition & 3 deletions src/runtime/plugins/refresh-token.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,7 @@ export default defineNuxtPlugin({
)
return
}
else {
rawRefreshToken.value = extractedRefreshToken
}
rawRefreshToken.value = extractedRefreshToken
}

rawToken.value = extractedToken
Expand Down
8 changes: 3 additions & 5 deletions src/runtime/server/services/authjs/nuxtAuthHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down

0 comments on commit 0f7e51a

Please sign in to comment.