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
  4. Guest mode: Only logged out people can view the page, more here

Briefly summarized, you can enable global protection (1) in your nuxt.config.ts:

export default defineNuxtConfig({   modules: ['@sidebase/nuxt-auth'],   auth: {    globalAppMiddleware: true   }})

Now all pages, aside from the login pages will require sign-in. Learn how to add excepted pages below

To enable page-local protection (2), add the following definePageMeta directive to a page:

<!-- file: ~/pages/protected.vue --><template>  <div>I'm protected!</div></template><script setup lang="ts">definePageMeta({ middleware: 'auth' })</script>

You cannot mix approach (1) and (2). So, if the global middleware is enabled, you cannot additionally add another protection middleware to a specific page.

Global middleware

To create a global authentication middleware that ensures that your user is authenticated no matter which page they visit, you configure nuxt-auth as follows:

export default defineNuxtConfig({  modules: ['@sidebase/nuxt-auth'],  auth: {    globalAppMiddleware: true  }})

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

Where to redirect authenticated users if unauthenticatedOnly is set to true

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 to turn auth off:

<!-- file: ~/pages/index.vue --><template>  <div>I'm publicly available!</div></template><script setup lang="ts">definePageMeta({ auth: false })</script>

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 to turn auth on:

<!-- file: ~/pages/unprotected.vue --><template>  <div>I'm protected! Only logged in users will see me</div></template><script setup lang="ts">definePageMeta({ middleware: 'auth' })</script>

Note: You cannot use local protection when you turned on the global middleware by setting globalAppMiddleware: true in the nuxt-auth configuration. You will get an error along the lines of "Error: Unknown route middleware: 'auth'". This is because the auth middleware is then added globally and not available to use as a local, page-specific middleware.

Custom middleware

You may create your own application-side middleware in order to implement custom, more advanced authentication logic.

Creating a custom middleware is an advanced, experimental option and may result in unexpected or undesired behavior if you are not familiar with advanced Nuxt 3 concepts.

To implement your custom middleware:

  1. Create an application-side middleware that applies either globally or is named (see the Nuxt docs for more)
  2. Add logic based on useAuth to it

When adding the logic, you need to watch out when calling other async composable functions. This can lead to context-problems in Nuxt, see the explanation for this here. In order to avoid these problems, you will need to either:

  • use the undocumented callWithNuxt utility when awaiting other composables,
  • return an async function where possible instead of awaiting it to avoid callWithNuxt

Following are examples of both kinds of usage:

direct return
// file: ~/middleware/authentication.global.tsexport default defineNuxtRouteMiddleware((to) => {  const { status, signIn } = useAuth()  // Return immediately if user is already authenticated  if (status.value === 'authenticated') {    return  }  /**   * We cannot directly call and/or return `signIn` here as `signIn` uses async composables under the hood, leading to "nuxt instance undefined errors", see https://github.com/nuxt/framework/issues/5740#issuecomment-1229197529   *   * So to avoid calling it, we return it immediately.   */  return signIn(undefined, { callbackUrl: to.path }) as ReturnType<typeof navigateTo>})
callWithNuxt
// file: ~/middleware/authentication.global.tsimport { useNuxtApp } from '#imports'import { callWithNuxt } from '#app/nuxt'export default defineNuxtRouteMiddleware((to) => {  // It's important to do this as early as possible  const nuxtApp = useNuxtApp()  const { status, signIn } = useAuth()  // Return immediately if user is already authenticated  if (status.value === 'authenticated') {    return  }  /**   * We cannot directly call and/or return `signIn` here as `signIn` uses async composables under the hood, leading to "nuxt instance undefined errors", see https://github.com/nuxt/framework/issues/5740#issuecomment-1229197529   *   * So to avoid calling it, we call it via `callWithNuxt`.   */  await callWithNuxt(nuxtApp, signIn, [undefined, { callbackUrl: to.path }])})

Guest Mode

Since v0.5.0 nuxt-auth also offers a guest mode. Checkout the guest mode documentation.