amannn / next-intl

🌐 Internationalization (i18n) for Next.js
https://next-intl-docs.vercel.app
MIT License
2.29k stars 211 forks source link

[Docs]: Example: Integrating with Supabase Authentication #719

Closed amannn closed 2 weeks ago

amannn commented 8 months ago

Link to page

https://next-intl-docs.vercel.app/docs/routing/middleware

Describe the problem

@supabase/auth-helpers-nextjs is deprecated:

We generally recommend using the new @supabase/ssr package instead of auth-helpers. @supabase/ssr takes the core concepts of the Auth Helpers package and makes them available to any server framework. Check out the migration doc to learn more.

It would be helpful if we update our example in the docs too. I don't have any experience with Supabase, therefore it would be helpful if someone who actively uses Supabase could adapt this.

@wscourge Since you've provided https://github.com/amannn/next-intl/pull/673, do you by chance know how to upgrade?

wscourge commented 8 months ago

I'll keep in mind doing it once done in my project.

abiddraws commented 8 months ago

Hi, Any update on this ? @wscourge have you given it a try?

wscourge commented 8 months ago

Nope. Have you?

mkbctrl commented 8 months ago

You need to create a Request/Response for client for serverless. Here is a generic function that allows to choose cookie methods:

import { CookieMethods, createServerClient } from '@supabase/ssr'

interface ComposeDbServerClientProps {
  cookieMethods?: () => CookieMethods
}

/**
 * Creates a server client for the database.
 * You can view the examples: https://supabase.com/docs/guides/auth/server-side/creating-a-client?environment=route-handler#creating-a-client
 */
export const composeDbServerClient = ({ cookieMethods }: ComposeDbServerClientProps) => {
  {
    if (!cookieMethods) {
      throw new Error('cookieMethods are required!')
    }

    const dbServerClient = createServerClient(
      process.env.NEXT_PUBLIC_SUPABASE_URL!,
      process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
      {
        cookies: cookieMethods(),
        auth: {
          flowType: 'pkce',
          autoRefreshToken: true,
          persistSession: true,
          detectSessionInUrl: true,
        },
      },
    )

    return {
      dbServerClient,
    }
  }
}

once you have compose you can create a client for SSR or Middleware environment (they have different inputs)

import { type CookieOptions } from '@supabase/ssr'

import { getCookie, setCookie } from 'cookies-next'
import { type NextRequest, type NextResponse } from 'next/server'
import { composeDbServerClient } from './compose-db-server-client'

/**
 * Function that returns an object with methods for handling cookies. Can be used as an argument to the createDbServerClient method in server scenarios.
 */
export const composeDbReqResClient = (req: NextRequest, res: NextResponse) => {
  return composeDbServerClient({
    cookieMethods: () => ({
      get(name: string) {
        return getCookie(name, { req, res })
      },
      set(name: string, value: string, options: CookieOptions) {
        return setCookie(name, value, { req, res, ...options })
      },
      remove(name: string, options: CookieOptions) {
        return setCookie(name, '', { req, res, ...options })
      },
    }),
  })
}

once you are able to create a dbClient for serverles, it's same old, same old as in the docs:

export async function middleware(req: NextRequest) {

  try {
    const res = i18nMiddleware(req)
    const { dbServerClient } = composeDbReqResClient(req, res)
    await dbServerClient.auth.getSession() // automatically refreshes the session if expired

    return res
  }

  ...

Hope it helps.

cookies-next package is pretty important here, abstracts a way a lot of boilerplate.

flixlix commented 6 months ago

Just made this PR, hope it helps: #856

amannn commented 2 weeks ago

There's another update coming to the Supabase authentication docs here: https://github.com/amannn/next-intl/pull/1260