Nuxt Supabase

repository·main·Indexed 21 days ago

https://github.com/nuxt-modules/supabase

A module that integrates Supabase into Nuxt 3 and 4 applications. It provides an isomorphic Supabase client for client and server contexts, Vue 3 composables, built-in authentication support with PKCE flow, and full TypeScript safety. Key features include automatic authentication redirects, SSR session management via cookies, and support for API server routes.

Tokens
13.7K
Snippets
46
Records
60
Agent score
74%

What's inside @nuxtjs/supabase

  1. Overview of Nuxt Supabase

    main

    Nuxt Supabase is a module for Nuxt that integrates Supabase into your application. It provides a seamless way to use Supabase services within the Nuxt ecosystem, supporting Nuxt 3 and 4. Key features include:

    • Vue 3 Composables: Easy access to Supabase functionality within your components.
    • Isomorphic Client: Uses the supabase-js client, which works in both the browser and server environments.
    • API Server Routes: Full support for using Supabase within Nuxt server routes.
    • Authentication: Built-in support for Supabase Auth.
    • TypeScript Support: Full type safety for your Supabase interactions.
  2. Key features of Nuxt Supabase

    main

    Nuxt Supabase is a wrapper around supabase-js designed for seamless integration with the Nuxt ecosystem. Key capabilities include:

    • Nuxt 3 and 4 Ready: Optimized for modern Nuxt versions.
    • Vue 3 Composables: Provides easy-to-use composables like useSupabaseClient().
    • Supabase-js V2: Full support for the latest Supabase JavaScript SDK.
    • API Server Route Support: Ability to use the Supabase client within Nuxt server routes.
    • Authentication Support: Built-in support for authentication using JWT signing keys.
    • TypeScript Support: Fully typed development experience.
  3. Configure Supabase authentication and session cookies

    main

    The useSsrCookies option (default: true) determines how session information is shared between the server and client.

    • Enabled (true): Uses @supabase/ssr to share session info via cookies. This is required if you need to access session or user info from the server.
    • Disabled (false): Uses @supabase/supabase-js which stores session info in local storage. This is useful for statically generated sites or mobile apps where cookies might not be available.

    Warning: When useSsrCookies is true, you cannot customize the following clientOptions: flowType, autoRefreshToken, detectSessionInUrl, persistSession, or storage. To customize these, you must set useSsrCookies to false (which disables SSR support).

    supabase: {
      useSsrCookies: true
    }
  4. Use useSupabaseCookieRedirect to handle post-login redirects

    main

    The useSupabaseCookieRedirect composable manages a redirect path stored in a cookie. This allows you to capture the URL a user was trying to visit before being prompted to log in, and then redirect them back to that specific path after successful authentication.

    Note: The redirect path is not automatically applied. You must implement the redirection logic yourself, typically on a confirmation page (like /confirm) by watching the user state.

    To automate the saving of the path, you can enable the saveRedirectToCookie option in your module configuration under redirectOptions.

    <script setup>
    const user = useSupabaseUser()
    const redirectInfo = useSupabaseCookieRedirect()
    
    watch(user, () => {
      if (user.value) {
        // Get the saved path and clear it from the cookie
        const path = redirectInfo.pluck()
        // Redirect to the saved path, or fallback to home
        return navigateTo(path || '/')
      }
    }, { immediate: true })
    </script>
  5. Fetch session during SSR with useFetch

    main

    When fetching a session route during Server-Side Rendering (SSR), you must explicitly pass the browser cookies (which include the Supabase token) to the request. If you do not include the cookie header, the server route will not be able to identify the session during the initial render.

    const session = ref(null)
    
    const { data } = await useFetch('/api/session', {
      headers: useRequestHeaders(['cookie'])
    })
    
    session.value = data
  6. Implement a password reset flow

    main

    A password reset flow involves two main steps:

    1. Request a password reset

    Use supabase.auth.resetPasswordForEmail to send a reset link to the user. You must specify a redirectTo URL where the user will be sent after clicking the link.

    2. Update the password

    Once the user is redirected back to your application via the reset link, prompt them for a new password and call supabase.auth.updateUser({ password: 'new-password' }).

    You can also listen for the PASSWORD_RECOVERY event using onAuthStateChange() to trigger the password update logic automatically when the recovery link is processed.

    // Step 1: Request reset
    const { data, error } = await supabase.auth.resetPasswordForEmail(email.value, {
      redirectTo: 'https://example.com/password/update',
    })
    
    // Step 2: Update password (can be triggered via event listener)
    watch(newPassword, () => {
      supabase.auth.onAuthStateChange(async (event, session) => {
        if (event == "PASSWORD_RECOVERY") {
          const { data, error } = await supabase.auth.updateUser({ password: newPassword.value })
        }
      })
    })
  7. Migrate from @nuxtjs/supabase v1.x to v2.x

    main

    This guide outlines the migration process from version 1.x to 2.x. The primary change is the introduction of support for Supabase's asymmetric JWT signing keys, which allows for local session verification without network calls to the Supabase Auth server.

    Key Changes Overview

    • Authentication: Moves from symmetric keys (shared secret) to asymmetric keys (private/public pair).
    • useSupabaseUser: Now returns JWT claims instead of the full User object.
    • Environment Variables: Renamed and repurposed to support the new key structure.

    Migration Summary

    1. Update Types: Adjust code that relies on the full User object returned by useSupabaseUser.
    2. Update Environment Variables: Transition from using the anon key to the publishable key and add the secret key.

    If you only need basic user information (like email or role), your code may not require any changes, but you must update your TypeScript definitions.

  8. Handle user redirection after login using `useSupabaseCookieRedirect`

    main

    To automatically redirect a user back to the page they were originally trying to access before being prompted to log in, follow these steps:

    1. Enable the saveRedirectToCookie option in your module configuration.
    2. On your /confirm page, use the useSupabaseCookieRedirect composable to retrieve and clear the saved path once the user is authenticated.

    If you prefer to manage the redirect path manually, you can disable saveRedirectToCookie and use useSupabaseCookieRedirect to set the value yourself.

    <script setup lang="ts">
    const user = useSupabaseUser()
    const redirectInfo = useSupabaseCookieRedirect()
    
    watch(user, () => {
      if (user.value) {
        // Get redirect path, and clear it from the cookie
        const path = redirectInfo.pluck()
        // Redirect to the saved path, or fallback to home
        return navigateTo(path || '/') 
      }
    }, { immediate: true })
    </script>
    
    <template>
      <div>Waiting for login...</div>
    </template>"}
  9. Pass client headers when fetching server routes during SSR

    main

    When calling a server route that uses serverSupabaseClient during Server-Side Rendering (SSR), you must ensure that the browser's cookies (which contain the Supabase authentication token) are passed to the API route. If you do not pass the cookie header, the server-side client will not be authenticated as the current user.

    When using useFetch, you can achieve this by passing the request headers using useRequestHeaders(['cookie']).

    // In a Vue component during SSR
    const { data: { libraries }} = await useFetch('/api/libraries', {
      headers: useRequestHeaders(['cookie'])
    })