该子模块为在Next中实现用户身份验证提供了方便的帮助Next.js应用程序。

安装Next.js助手库

设置环境变量

在项目的应用设置->API中检索项目URL和匿名密钥以设置以下环境变量。对于本地开发,可以在.env.local文件。参见示例

  NEXT_PUBLIC_SUPABASE_URL=YOUR_SUPABASE_URL
NEXT_PUBLIC_SUPABASE_ANON_KEY=YOUR_SUPABASE_ANON_KEY
  

基本设置

现在,您可以通过检查 useUser()钩子返回的user对象是否已定义来确定用户是否已通过身份验证。

使用RLS获取客户端数据

为了使行级别安全在客户端获取数据时正常工作,您需要确保使用supabaseClient钩子中的 useSupabaseClient,并且仅在 useUser()钩子中定义了客户端用户后才运行查询:

  import { Auth, ThemeSupa } from '@supabase/auth-ui-react'
import { useUser, useSupabaseClient } from '@supabase/auth-helpers-react'
import { useEffect, useState } from 'react'

const LoginPage = () => {
  const supabaseClient = useSupabaseClient()
  const user = useUser()
  const [data, setData] = useState()

  useEffect(() => {
    async function loadData() {
      const { data } = await supabaseClient.from('test').select('*')
      setData(data)
    }
    // Only run query once user is logged in.
    if (user) loadData()
  }, [user])

  if (!user)
    return (
      <Auth
        redirectTo="http://localhost:3000/"
        appearance={{ theme: ThemeSupa }}
        supabaseClient={supabaseClient}
        providers={['google', 'github']}
        socialLayout="horizontal"
      />
    )

  return (
    <>
      <button onClick={() => supabaseClient.auth.signOut()}>Sign out</button>
      <p>user:</p>
      <pre>{JSON.stringify(user, null, 2)}</pre>
      <p>client-side data fetching with RLS</p>
      <pre>{JSON.stringify(data, null, 2)}</pre>
    </>
  )
}

export default LoginPage
  

服务器端渲染 (SSR)

创建服务器超级客户端以检索登录用户的会话:

  import { createServerSupabaseClient } from '@supabase/auth-helpers-nextjs'

export default function Profile({ user }) {
  return <div>Hello {user.name}</div>
}

export const getServerSideProps = async (ctx) => {
  // Create authenticated Supabase Client
  const supabase = createServerSupabaseClient(ctx)
  // Check if we have a session
  const {
    data: { session },
  } = await supabase.auth.getSession()

  if (!session)
    return {
      redirect: {
        destination: '/',
        permanent: false,
      },
    }

  return {
    props: {
      initialSession: session,
      user: session.user,
    },
  }
}
  

使用RLS获取服务器端数据

您可以使用服务器超级数据库客户端运行行级别安全性服务器端验证查询:

使用 provider token将服务器端数据提取到OAuth API

当使用第三方身份验证提供程序时,会话将使用附加的 provider_token字段启动,该字段保存在身份验证cookie中,可以在会话对象中访问。provider_token可用于代表登录用户向OAuth提供程序的API端点发出API请求。

保护API路由

创建服务器超级客户端以检索登录用户的会话:

使用Next.js中间件进行身份验证。

作为保护单个页面的替代方案,您可以使用Next.js中间件以保护整个目录或与配置对象匹配的目录。在以下示例中,所有对/middleware protected/*的请求都将检查用户是否已登录,如果成功,请求将被转发到目标路由,否则用户将被重定向:

  import { createMiddlewareSupabaseClient } from '@supabase/auth-helpers-nextjs'
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export async function middleware(req: NextRequest) {
  // We need to create a response and hand it to the supabase client to be able to modify the response headers.
  const res = NextResponse.next()
  // Create authenticated Supabase Client.
  const supabase = createMiddlewareSupabaseClient({ req, res })
  // Check if we have a session
  const {
    data: { session },
  } = await supabase.auth.getSession()

  // Check auth condition
  if (session?.user.email?.endsWith('@gmail.com')) {
    // Authentication successful, forward request to protected route.
    return res
  }

  // Auth condition not met, redirect to home page.
  const redirectUrl = req.nextUrl.clone()
  redirectUrl.pathname = '/'
  redirectUrl.searchParams.set(`redirectedFrom`, req.nextUrl.pathname)
  return NextResponse.redirect(redirectUrl)
}

export const config = {
  matcher: '/middleware-protected',
}
  

迁移指南

迁移到v0.5.X

使这些助手更灵活,更易于维护,更易于为新版本的Next.js升级,我们将其分解为最有用的部分,即管理cookie,并在任何环境(客户端、服务器、中间件/边缘)中为您提供经过认证的超级js客户端。

因此,我们将withApiAuthwithPageAuthwithMiddlewareAuth高阶函数标记为已弃用,它们将在下一个次要版本(v0.6.X)中删除。

请按照以下步骤更新API路由、页面和中间件处理程序。谢谢

withApiAuth已弃用!

NextApiHandler中使用createServerSubaseClient

withPageAuth已弃用!

getServerSideProps中使用createServerSubaseClient

withMiddlewareAuth已弃用!

迁移到v0.4.X和supabase js v2

随着supabase-js v2的更新,不再需要 authAPI路由,因此您可以继续删除 /pages/api/目录下的 auth目录。请参阅v2迁移指南以了解supabase js中的全部更改。

/api/auth/logout api路由已删除,请改用 signout 方法:

  <button
  onClick={async () => {
    await supabaseClient.auth.signOut()
    router.push('/')
  }}
>
  Logout
</button>
  

已删除supabaseClientsupabaseServerClient,改用createBrowserSupbaseClientcreateServerSubaseClient方法。这允许您向客户端提供CLI生成的类型:

  // client-side
import type { Database } from 'types_db'
const [supabaseClient] = useState(() => createBrowserSupabaseClient<Database>())

// server-side API route
import type { NextApiRequest, NextApiResponse } from 'next'
import type { Database } from 'types_db'

export default async (req: NextApiRequest, res: NextApiResponse) => {
  const supabaseServerClient = createServerSupabaseClient<Database>({
    req,
    res,
  })
  const {
    data: { user },
  } = await supabaseServerClient.auth.getUser()

  res.status(200).json({ name: user?.name ?? '' })
}
  
  • UserProvider 已被 SessionContextProvider替换。确保包装您的 pages/_app.jsSessionContextProvider兼容。然后,在整个应用程序中,您可以使用 useSessionContext钩子获取 session,使用useSubaseClient钩子获取经过身份验证的supbaseClient
  • useUser钩子现在返回user对象或null
  • TypeScript的用法:您可以将使用Suabase CLI生成的类型传递给Supabase客户端,以获得增强的类型安全性和自动完成:

创建新的超级数据库客户端对象:

  import { Database } from '../database.types'

const [supabaseClient] = useState(() => createBrowserSupabaseClient<Database>())
  

从SessionContext中检索超级客户端对象:

  import { useSupabaseClient } from '@supabase/auth-helpers-react'
import { Database } from '../database.types'

const supabaseClient = useSupabaseClient<Database>()