Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: protected route redirect overwrite per page #424

Merged
merged 13 commits into from
Sep 23, 2023
3 changes: 2 additions & 1 deletion docs/content/3.application-side/4.protecting-pages.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Protecting Pages

`nuxt-auth` offers different approaches to protect pages:

1. Global protection: Protects all pages with manual exceptions
2. Local protection: Protects specific pages
3. Custom middleware: Create your own middleware
Expand Down Expand Up @@ -48,6 +49,7 @@ That's it! Every page of your application will now need authentication for the u
### Disabling the global middleware locally

To disable the global middleware on a specific page only, you can use the [`definePageMeta` macro](https://nuxt.com/docs/api/utils/define-page-meta#definepagemeta) to turn `auth` off:

```vue
<!-- file: ~/pages/index.vue -->
<template>
Expand All @@ -61,7 +63,6 @@ definePageMeta({ auth: false })

Note: This only works on `pages/`. It notably does not work inside the `app.vue`.


## Local middleware

To protect specific pages with a middleware, you can use the [`definePageMeta` macro](https://nuxt.com/docs/api/utils/define-page-meta#definepagemeta) to turn `auth` on:
Expand Down
14 changes: 14 additions & 0 deletions docs/content/v0.6/3.application-side/4.protecting-pages.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,20 @@ export default defineNuxtConfig({

That's it! Every page of your application will now need authentication for the user to visit it.

### Middleware Options

#### `unauthenticatedOnly`

Whether to only allow unauthenticated users to access this page. Authenticated users will be redirected to `/` or the route defined in `navigateAuthenticatedTo`

#### `navigateAuthenticatedTo`

Where to redirect authenticated users if `unauthenticatedOnly` is set to true

#### `navigateUnauthenticatedTo`

Where to redirect unauthenticated users if this page is protected

### Disabling the global middleware locally

To disable the global middleware on a specific page only, you can use the [`definePageMeta` macro](https://nuxt.com/docs/api/utils/define-page-meta#definepagemeta) to turn `auth` off:
Expand Down
27 changes: 25 additions & 2 deletions src/runtime/middleware/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,23 @@ import { navigateToAuthPages, determineCallbackUrl } from '../utils/url'
import { useAuth } from '#imports'

type MiddlewareMeta = boolean | {
unauthenticatedOnly: true,
/** Whether to only allow unauthenticated users to access this page.
*
* Authenticated users will be redirected to `/` or the route defined in `navigateAuthenticatedTo`
*
* @default undefined
*/
unauthenticatedOnly?: boolean,
zoey-kaiser marked this conversation as resolved.
Show resolved Hide resolved
/** Where to redirect authenticated users if `unauthenticatedOnly` is set to true
*
* @default undefined
*/
navigateAuthenticatedTo?: string,
/** Where to redirect unauthenticated users if this page is protected
*
* @default undefined
*/
navigateUnauthenticatedTo?: string
}

declare module '#app/../pages/runtime/composables' {
Expand All @@ -14,7 +29,13 @@ declare module '#app/../pages/runtime/composables' {
}

export default defineNuxtRouteMiddleware((to) => {
const metaAuth = to.meta.auth
const metaAuth = typeof to.meta.auth === 'object'
? {
unauthenticatedOnly: true,
...to.meta.auth
}
: to.meta.auth

if (metaAuth === false) {
return
}
Expand Down Expand Up @@ -60,6 +81,8 @@ export default defineNuxtRouteMiddleware((to) => {
const signInOptions: Parameters<typeof signIn>[1] = { error: 'SessionRequired', callbackUrl: determineCallbackUrl(authConfig, () => to.path) }
// @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)
} else {
return navigateTo(authConfig.provider.pages.login)
}
Expand Down