mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 01:15:03 +03:00
docs: Update auth-helpers usage from examples (#43345)
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES
This commit is contained in:
1 parent
96ac1c2652
commit
579357089b
16 files changed
+166
-136
No files matched your search
@@ -0,0 +1,34 @@
|
||||
import { createBrowserClient } from '@supabase/ssr'
|
||||
import { User } from '@supabase/supabase-js'
|
||||
import { createContext, useContext, useEffect, useState } from 'react'
|
||||
|
||||
const supabase = createBrowserClient(
|
||||
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
||||
process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!
|
||||
)
|
||||
|
||||
type SupabaseContextType = {
|
||||
supabase: typeof supabase
|
||||
user: User | null
|
||||
}
|
||||
|
||||
const SupabaseContext = createContext<SupabaseContextType>({ supabase, user: null })
|
||||
|
||||
export function SupabaseProvider({ children }: { children: React.ReactNode }) {
|
||||
const [user, setUser] = useState<User | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
supabase.auth.getUser().then(({ data: { user } }) => setUser(user))
|
||||
|
||||
const {
|
||||
data: { subscription },
|
||||
} = supabase.auth.onAuthStateChange((_event, session) => setUser(session?.user ?? null))
|
||||
|
||||
return () => subscription.unsubscribe()
|
||||
}, [])
|
||||
|
||||
return <SupabaseContext.Provider value={{ supabase, user }}>{children}</SupabaseContext.Provider>
|
||||
}
|
||||
|
||||
export const useSupabaseClient = () => useContext(SupabaseContext).supabase
|
||||
export const useUser = () => useContext(SupabaseContext).user
|
||||
@@ -10,9 +10,8 @@
|
||||
"format": "prettier --cache --write \"pages/**/*.{js,jsx,ts,tsx,css,md,json}\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@supabase/auth-helpers-nextjs": "^0.6.0",
|
||||
"@supabase/auth-helpers-react": "^0.3.1",
|
||||
"@supabase/auth-ui-react": "^0.2.7",
|
||||
"@supabase/auth-ui-react": "^0.4.7",
|
||||
"@supabase/ssr": "latest",
|
||||
"@supabase/supabase-js": "^2.7.1",
|
||||
"next": "^13.1.6",
|
||||
"react": "^18.2.0",
|
||||
|
||||
@@ -1,23 +1,17 @@
|
||||
import { createBrowserSupabaseClient, Session } from '@supabase/auth-helpers-nextjs'
|
||||
import { SessionContextProvider } from '@supabase/auth-helpers-react'
|
||||
import { SupabaseProvider, useSupabaseClient } from '@/lib/supabase-context'
|
||||
import type { AppProps } from 'next/app'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useEffect } from 'react'
|
||||
import '../styles/globals.css'
|
||||
|
||||
function MyApp({
|
||||
Component,
|
||||
pageProps,
|
||||
}: AppProps<{
|
||||
initialSession: Session
|
||||
}>) {
|
||||
function MyAppInner({ Component, pageProps }: AppProps) {
|
||||
const router = useRouter()
|
||||
const [supabaseClient] = useState(() => createBrowserSupabaseClient())
|
||||
const supabase = useSupabaseClient()
|
||||
|
||||
useEffect(() => {
|
||||
const {
|
||||
data: { subscription },
|
||||
} = supabaseClient.auth.onAuthStateChange((event, session) => {
|
||||
} = supabase.auth.onAuthStateChange((event) => {
|
||||
switch (event) {
|
||||
case 'SIGNED_IN':
|
||||
router.push('/')
|
||||
@@ -28,15 +22,16 @@ function MyApp({
|
||||
}
|
||||
})
|
||||
return subscription.unsubscribe
|
||||
}, [])
|
||||
}, [supabase, router])
|
||||
|
||||
return <Component {...pageProps} />
|
||||
}
|
||||
|
||||
function MyApp(props: AppProps) {
|
||||
return (
|
||||
<SessionContextProvider
|
||||
supabaseClient={supabaseClient}
|
||||
initialSession={pageProps.initialSession}
|
||||
>
|
||||
<Component {...pageProps} />
|
||||
</SessionContextProvider>
|
||||
<SupabaseProvider>
|
||||
<MyAppInner {...props} />
|
||||
</SupabaseProvider>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { createServerSupabaseClient } from '@supabase/auth-helpers-nextjs'
|
||||
import { useSupabaseClient, useUser } from '@supabase/auth-helpers-react'
|
||||
import { useSupabaseClient, useUser } from '@/lib/supabase-context'
|
||||
import { createServerClient } from '@supabase/ssr'
|
||||
import { serialize } from 'cookie'
|
||||
import { RealtimePresenceState } from '@supabase/supabase-js'
|
||||
import type { GetServerSidePropsContext, NextPage } from 'next'
|
||||
import { useEffect, useState } from 'react'
|
||||
@@ -54,14 +55,35 @@ const HomePage: NextPage = () => {
|
||||
}
|
||||
|
||||
export const getServerSideProps = async (ctx: GetServerSidePropsContext) => {
|
||||
// Create authenticated Supabase Client
|
||||
const supabase = createServerSupabaseClient(ctx)
|
||||
// Check if we have a session
|
||||
const {
|
||||
data: { session },
|
||||
} = await supabase.auth.getSession()
|
||||
const supabase = createServerClient(
|
||||
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
||||
process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!,
|
||||
{
|
||||
cookies: {
|
||||
getAll() {
|
||||
return Object.entries(ctx.req.cookies).map(([name, value]) => ({
|
||||
name,
|
||||
value: value ?? '',
|
||||
}))
|
||||
},
|
||||
setAll(cookiesToSet) {
|
||||
const existing = ctx.res.getHeader('Set-Cookie') ?? []
|
||||
ctx.res.setHeader('Set-Cookie', [
|
||||
...(Array.isArray(existing) ? existing : [String(existing)]),
|
||||
...cookiesToSet.map(({ name, value, options }) =>
|
||||
serialize(name, value, options)
|
||||
),
|
||||
])
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
if (!session)
|
||||
const {
|
||||
data: { user },
|
||||
} = await supabase.auth.getUser()
|
||||
|
||||
if (!user)
|
||||
return {
|
||||
redirect: {
|
||||
destination: '/login',
|
||||
@@ -71,8 +93,7 @@ export const getServerSideProps = async (ctx: GetServerSidePropsContext) => {
|
||||
|
||||
return {
|
||||
props: {
|
||||
initialSession: session,
|
||||
user: session.user,
|
||||
user,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useSupabaseClient, useUser } from '@supabase/auth-helpers-react'
|
||||
import { useSupabaseClient, useUser } from '@/lib/supabase-context'
|
||||
import { Auth, ThemeSupa } from '@supabase/auth-ui-react'
|
||||
import type { NextPage } from 'next'
|
||||
import styles from '../styles/Home.module.css'
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { createServerSupabaseClient, User } from '@supabase/auth-helpers-nextjs'
|
||||
import { createServerClient } from '@supabase/ssr'
|
||||
import { serialize } from 'cookie'
|
||||
import { User } from '@supabase/supabase-js'
|
||||
import { GetServerSidePropsContext } from 'next'
|
||||
import Link from 'next/link'
|
||||
|
||||
@@ -15,14 +17,35 @@ export default function Profile({ user }: { user: User }) {
|
||||
}
|
||||
|
||||
export const getServerSideProps = async (ctx: GetServerSidePropsContext) => {
|
||||
// Create authenticated Supabase Client
|
||||
const supabase = createServerSupabaseClient(ctx)
|
||||
// Check if we have a session
|
||||
const {
|
||||
data: { session },
|
||||
} = await supabase.auth.getSession()
|
||||
const supabase = createServerClient(
|
||||
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
||||
process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!,
|
||||
{
|
||||
cookies: {
|
||||
getAll() {
|
||||
return Object.entries(ctx.req.cookies).map(([name, value]) => ({
|
||||
name,
|
||||
value: value ?? '',
|
||||
}))
|
||||
},
|
||||
setAll(cookiesToSet) {
|
||||
const existing = ctx.res.getHeader('Set-Cookie') ?? []
|
||||
ctx.res.setHeader('Set-Cookie', [
|
||||
...(Array.isArray(existing) ? existing : [String(existing)]),
|
||||
...cookiesToSet.map(({ name, value, options }) =>
|
||||
serialize(name, value, options)
|
||||
),
|
||||
])
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
if (!session)
|
||||
const {
|
||||
data: { user },
|
||||
} = await supabase.auth.getUser()
|
||||
|
||||
if (!user)
|
||||
return {
|
||||
redirect: {
|
||||
destination: '/login',
|
||||
@@ -32,8 +55,7 @@ export const getServerSideProps = async (ctx: GetServerSidePropsContext) => {
|
||||
|
||||
return {
|
||||
props: {
|
||||
initialSession: session,
|
||||
user: session.user,
|
||||
user,
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
'use client'
|
||||
import CreateRoomModal from '@/components/create-room-modal'
|
||||
import { User, createClientComponentClient } from '@supabase/auth-helpers-nextjs'
|
||||
import { createClient } from '@/utils/supabase/client'
|
||||
import { User } from '@supabase/supabase-js'
|
||||
import { RealtimeChannel } from '@supabase/supabase-js'
|
||||
import { useState, useEffect, use } from 'react'
|
||||
|
||||
@@ -15,7 +16,7 @@ export default function Chat() {
|
||||
const [showModal, setShowModal] = useState<boolean>(false)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
|
||||
const supabase = createClientComponentClient()
|
||||
const supabase = createClient()
|
||||
|
||||
const getChannels = async () => {
|
||||
const channels = await supabase.from('rooms').select('topic')
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
"start": "next start"
|
||||
},
|
||||
"dependencies": {
|
||||
"@supabase/auth-helpers-nextjs": "^0.9.0",
|
||||
"@supabase/ssr": "latest",
|
||||
"@supabase/supabase-js": "2.44.0",
|
||||
"autoprefixer": "10.4.17",
|
||||
|
||||
@@ -1,60 +1,26 @@
|
||||
import { createServerClient, type CookieOptions } from "@supabase/ssr";
|
||||
import { createServerClient } from "@supabase/ssr";
|
||||
import { type NextRequest, NextResponse } from "next/server";
|
||||
|
||||
export const updateSession = async (request: NextRequest) => {
|
||||
// This `try/catch` block is only here for the interactive tutorial.
|
||||
// Feel free to remove once you have Supabase connected.
|
||||
try {
|
||||
// Create an unmodified response
|
||||
let response = NextResponse.next({
|
||||
request: {
|
||||
headers: request.headers,
|
||||
},
|
||||
});
|
||||
let supabaseResponse = NextResponse.next({ request });
|
||||
|
||||
const supabase = createServerClient(
|
||||
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
||||
process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!,
|
||||
{
|
||||
cookies: {
|
||||
get(name: string) {
|
||||
return request.cookies.get(name)?.value;
|
||||
getAll() {
|
||||
return request.cookies.getAll();
|
||||
},
|
||||
set(name: string, value: string, options: CookieOptions) {
|
||||
// If the cookie is updated, update the cookies for the request and response
|
||||
request.cookies.set({
|
||||
name,
|
||||
value,
|
||||
...options,
|
||||
});
|
||||
response = NextResponse.next({
|
||||
request: {
|
||||
headers: request.headers,
|
||||
},
|
||||
});
|
||||
response.cookies.set({
|
||||
name,
|
||||
value,
|
||||
...options,
|
||||
});
|
||||
},
|
||||
remove(name: string, options: CookieOptions) {
|
||||
// If the cookie is removed, update the cookies for the request and response
|
||||
request.cookies.set({
|
||||
name,
|
||||
value: "",
|
||||
...options,
|
||||
});
|
||||
response = NextResponse.next({
|
||||
request: {
|
||||
headers: request.headers,
|
||||
},
|
||||
});
|
||||
response.cookies.set({
|
||||
name,
|
||||
value: "",
|
||||
...options,
|
||||
});
|
||||
setAll(cookiesToSet) {
|
||||
cookiesToSet.forEach(({ name, value }) => request.cookies.set(name, value));
|
||||
supabaseResponse = NextResponse.next({ request });
|
||||
cookiesToSet.forEach(({ name, value, options }) =>
|
||||
supabaseResponse.cookies.set(name, value, options)
|
||||
);
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -64,15 +30,11 @@ export const updateSession = async (request: NextRequest) => {
|
||||
// https://supabase.com/docs/guides/auth/server-side/nextjs
|
||||
await supabase.auth.getUser();
|
||||
|
||||
return response;
|
||||
return supabaseResponse;
|
||||
} catch (e) {
|
||||
// If you are here, a Supabase client could not be created!
|
||||
// This is likely because you have not set up environment variables.
|
||||
// Check out http://localhost:3000 for Next Steps.
|
||||
return NextResponse.next({
|
||||
request: {
|
||||
headers: request.headers,
|
||||
},
|
||||
});
|
||||
return NextResponse.next({ request });
|
||||
}
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
import { createServerClient, type CookieOptions } from '@supabase/ssr'
|
||||
import { createServerClient } from '@supabase/ssr'
|
||||
import { cookies } from 'next/headers'
|
||||
|
||||
export const createClient = async () => {
|
||||
@@ -9,23 +9,16 @@ export const createClient = async () => {
|
||||
process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!,
|
||||
{
|
||||
cookies: {
|
||||
get(name: string) {
|
||||
return cookieStore.get(name)?.value
|
||||
getAll() {
|
||||
return cookieStore.getAll()
|
||||
},
|
||||
set(name: string, value: string, options: CookieOptions) {
|
||||
setAll(cookiesToSet) {
|
||||
try {
|
||||
cookieStore.set({ name, value, ...options })
|
||||
} catch (error) {
|
||||
// The `set` method was called from a Server Component.
|
||||
// This can be ignored if you have proxy refreshing
|
||||
// user sessions.
|
||||
}
|
||||
},
|
||||
remove(name: string, options: CookieOptions) {
|
||||
try {
|
||||
cookieStore.set({ name, value: '', ...options })
|
||||
} catch (error) {
|
||||
// The `delete` method was called from a Server Component.
|
||||
cookiesToSet.forEach(({ name, value, options }) =>
|
||||
cookieStore.set(name, value, options)
|
||||
)
|
||||
} catch {
|
||||
// The `setAll` method was called from a Server Component.
|
||||
// This can be ignored if you have proxy refreshing
|
||||
// user sessions.
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { Database } from '@/lib/schema'
|
||||
import { Session, useSupabaseClient } from '@supabase/auth-helpers-react'
|
||||
import { supabase } from '@/lib/initSupabase'
|
||||
import { Session } from '@supabase/supabase-js'
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
type Todos = Database['public']['Tables']['todos']['Row']
|
||||
|
||||
export default function TodoList({ session }: { session: Session }) {
|
||||
const supabase = useSupabaseClient<Database>()
|
||||
const [todos, setTodos] = useState<Todos[]>([])
|
||||
const [newTaskText, setNewTaskText] = useState('')
|
||||
const [errorText, setErrorText] = useState('')
|
||||
@@ -24,7 +24,7 @@ export default function TodoList({ session }: { session: Session }) {
|
||||
}
|
||||
|
||||
fetchTodos()
|
||||
}, [supabase])
|
||||
}, [])
|
||||
|
||||
const addTodo = async (taskText: string) => {
|
||||
let task = taskText.trim()
|
||||
@@ -90,7 +90,6 @@ export default function TodoList({ session }: { session: Session }) {
|
||||
}
|
||||
|
||||
const Todo = ({ todo, onDelete }: { todo: Todos; onDelete: () => void }) => {
|
||||
const supabase = useSupabaseClient<Database>()
|
||||
const [isCompleted, setIsCompleted] = useState(todo.is_complete)
|
||||
|
||||
const toggle = async () => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createClient } from '@supabase/supabase-js'
|
||||
import { createBrowserClient } from '@supabase/ssr'
|
||||
|
||||
export const supabase = createClient(
|
||||
process.env.NEXT_PUBLIC_SUPABASE_URL ?? '',
|
||||
process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY ?? ''
|
||||
export const supabase = createBrowserClient(
|
||||
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
||||
process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!
|
||||
)
|
||||
@@ -12,8 +12,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@next/font": "13.1.6",
|
||||
"@supabase/auth-helpers-react": "^0.3.1",
|
||||
"@supabase/auth-ui-react": "^0.2.8",
|
||||
"@supabase/auth-ui-react": "^0.4.7",
|
||||
"@supabase/ssr": "latest",
|
||||
"@supabase/supabase-js": "^2.8.0",
|
||||
"@types/node": "18.14.0",
|
||||
"@types/react": "18.0.28",
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
import { supabase } from '@/lib/initSupabase'
|
||||
import '@/styles/app.css'
|
||||
import { SessionContextProvider } from '@supabase/auth-helpers-react'
|
||||
import type { AppProps } from 'next/app'
|
||||
|
||||
export default function App({ Component, pageProps }: AppProps) {
|
||||
return (
|
||||
<SessionContextProvider supabaseClient={supabase}>
|
||||
<Component {...pageProps} />
|
||||
</SessionContextProvider>
|
||||
)
|
||||
return <Component {...pageProps} />
|
||||
}
|
||||
@@ -1,11 +1,22 @@
|
||||
import Head from 'next/head'
|
||||
import { useSession, useSupabaseClient } from '@supabase/auth-helpers-react'
|
||||
import { supabase } from '@/lib/initSupabase'
|
||||
import { Auth, ThemeSupa } from '@supabase/auth-ui-react'
|
||||
import TodoList from '@/components/TodoList'
|
||||
import { Session } from '@supabase/supabase-js'
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
export default function Home() {
|
||||
const session = useSession()
|
||||
const supabase = useSupabaseClient()
|
||||
const [session, setSession] = useState<Session | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
supabase.auth.getSession().then(({ data: { session } }) => setSession(session))
|
||||
|
||||
const {
|
||||
data: { subscription },
|
||||
} = supabase.auth.onAuthStateChange((_event, session) => setSession(session))
|
||||
|
||||
return () => subscription.unsubscribe()
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -5,8 +5,8 @@ This example will set you up for a very common situation: users can sign up or s
|
||||
This demonstrates how to use:
|
||||
|
||||
- User signups using Supabase [Auth](https://supabase.com/auth).
|
||||
- Supabase [Auth Helpers for Next.js](https://supabase.com/docs/guides/auth/auth-helpers/nextjs).
|
||||
- Supabase [pre-built Auth UI for React](https://supabase.com/docs/guides/auth/auth-helpers/auth-ui).
|
||||
- Supabase [SSR Auth for Next.js](https://supabase.com/docs/guides/auth/server-side/nextjs).
|
||||
- Supabase [pre-built Auth UI for React](https://supabase.com/docs/guides/auth/auth-ui).
|
||||
- User avatar images using Supabase [Storage](https://supabase.com/storage)
|
||||
- Public profiles restricted with [Policies](https://supabase.com/docs/guides/auth#policies).
|
||||
- Frontend using [Next.js](<[nextjs.org/](https://nextjs.org/)>).
|
||||
@@ -16,8 +16,8 @@ This demonstrates how to use:
|
||||
- Frontend:
|
||||
- [Next.js](https://github.com/vercel/next.js) - a React framework for production.
|
||||
- [Supabase.js](https://supabase.com/docs/library/getting-started) for user management and realtime data syncing.
|
||||
- Supabase [Auth Helpers for Next.js](https://supabase.com/docs/guides/auth/auth-helpers/nextjs).
|
||||
- Supabase [pre-built Auth UI for React](https://supabase.com/docs/guides/auth/auth-helpers/auth-ui).
|
||||
- Supabase [`@supabase/ssr`](https://supabase.com/docs/guides/auth/server-side/nextjs) for SSR auth.
|
||||
- Supabase [pre-built Auth UI for React](https://supabase.com/docs/guides/auth/auth-ui).
|
||||
- Backend:
|
||||
- [supabase.com/dashboard](https://supabase.com/dashboard/): hosted Postgres database with restful API for usage with Supabase.js.
|
||||
|
||||
|
||||
Reference in new issue
Block a user