Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion src/app/api/v1/auth/api-keys/route.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { NextRequest, NextResponse } from 'next/server'
import { createServerClient } from '@/lib/supabase'
import { createServerClient, createSSRClient } from '@/lib/supabase'
import bcrypt from 'bcryptjs'
import crypto from 'crypto'

Expand All @@ -12,6 +12,13 @@ async function getAuthContext(req: NextRequest) {
const walletAddress = getWalletAddress(req)
if (!walletAddress) return null

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Flash Review

The use of createSSRClient in an API route (/api/v1/*) might be problematic. createSSRClient is typically designed for Server Components or getServerSideProps contexts, where it implicitly handles cookies. In API routes, createServerClient (from @supabase/auth-helpers-nextjs) is usually preferred, explicitly passing cookies() from next/headers to ensure the session cookie is correctly read from the NextRequest. If createSSRClient isn't specifically configured to handle NextRequest cookies in this context, supabaseSsr.auth.getUser() might incorrectly return null, leading to authentication failures for legitimate users.

Fix: Verify that createSSRClient is robustly implemented to read session cookies from NextRequest in API routes. If not, consider using createServerClient with cookies() from next/headers for consistency and reliability in API authentication.


const supabaseSsr = await createSSRClient()
const { data: { user } } = await supabaseSsr.auth.getUser()

if (!user || user.user_metadata?.wallet_address !== walletAddress) {
return null
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const supabase = createServerClient() as any
return { supabase, walletAddress }
Expand Down
27 changes: 26 additions & 1 deletion src/lib/supabase.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { createBrowserClient } from '@supabase/ssr'
import { createBrowserClient, createServerClient as createSupabaseSSRClient } from '@supabase/ssr'
import { createClient as createSupabaseClient, SupabaseClient } from '@supabase/supabase-js'
import { Database } from '@/types/database.types'
import { cookies } from 'next/headers'

// Client-side (Browser)
export const createClient = () =>
Expand All @@ -9,9 +10,33 @@ export const createClient = () =>
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
)

// Server-side (SSR with cookies)
export const createSSRClient = async () => {
const cookieStore = await cookies()
return createSupabaseSSRClient<Database>(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
get(name: string) {
return cookieStore.get(name)?.value
},
set(name: string, value: string, options: any) {
try { cookieStore.set({ name, value, ...options }) } catch (error) {}
},
remove(name: string, options: any) {
try { cookieStore.delete({ name, ...options }) } catch (error) {}
},
},
}
)
}

// Server-side (API Routes, Services, Background Jobs)
export const createServerClient = () =>
createSupabaseClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.SUPABASE_SERVICE_ROLE_KEY || process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
) as SupabaseClient<Database>

export const createAdminClient = createServerClient
Loading