Skip to content

Commit 9e037ac

Browse files
committed
fix: use correct supabase auth in stripe-setup edge-function
1 parent 3645f38 commit 9e037ac

1 file changed

Lines changed: 94 additions & 0 deletions

File tree

packages/sync-engine/src/supabase/edge-functions/stripe-setup.ts

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,95 @@ const MGMT_API_BASE = MGMT_API_BASE_RAW.match(/^https?:\/\//)
1212
? MGMT_API_BASE_RAW
1313
: `https://${MGMT_API_BASE_RAW}`
1414

15+
// Returns true if the projectRef passed is a non-branch project, false otherwise
16+
async function canAccessProject(projectRef: string, accessToken: string): Promise<boolean> {
17+
const url = `${MGMT_API_BASE}/v1/projects/${projectRef}`
18+
const response = await fetch(url, {
19+
method: 'GET',
20+
headers: {
21+
Authorization: `Bearer ${accessToken}`,
22+
'Content-Type': 'application/json',
23+
},
24+
})
25+
return response.ok
26+
}
27+
28+
// Returns all projects refs
29+
async function getAllProjects(accessToken: string): Promise<string[]> {
30+
const url = `${MGMT_API_BASE}/v1/projects`
31+
const response = await fetch(url, {
32+
method: 'GET',
33+
headers: {
34+
Authorization: `Bearer ${accessToken}`,
35+
'Content-Type': 'application/json',
36+
},
37+
})
38+
if (response.ok) {
39+
const projects = (await response.json()) as Array<{ ref?: string }>
40+
return Array.isArray(projects)
41+
? projects
42+
.map((project) => project.ref)
43+
.filter((projectRef): projectRef is string => Boolean(projectRef))
44+
: []
45+
} else {
46+
return []
47+
}
48+
}
49+
50+
// Returns all branch project refs of a give projectRef
51+
async function getAllBranches(projectRef: string, accessToken: string): Promise<string[]> {
52+
const url = `${MGMT_API_BASE}/v1/projects/${projectRef}/branches`
53+
const response = await fetch(url, {
54+
method: 'GET',
55+
headers: {
56+
Authorization: `Bearer ${accessToken}`,
57+
'Content-Type': 'application/json',
58+
},
59+
})
60+
if (response.ok) {
61+
const branches = (await response.json()) as Array<{ project_ref?: string }>
62+
return Array.isArray(branches)
63+
? branches
64+
.map((branch) => branch.project_ref)
65+
.filter((projectRef): projectRef is string => Boolean(projectRef))
66+
: []
67+
} else {
68+
return []
69+
}
70+
}
71+
72+
// Authenticates with Supabase management API. Returns null if the accessToken has
73+
// access to the projectRef project, other returns an error string
74+
async function authenticateWithSupabase(
75+
projectRef: string,
76+
accessToken: string | null
77+
): Promise<string | null> {
78+
if (!accessToken) {
79+
return 'Unauthorized: Invalid credentials'
80+
}
81+
82+
// First we check if the token can return the project directly
83+
// If it does then the token is valid for this project and
84+
// we authenticate the request
85+
const tokenCanAccesProject = await canAccessProject(projectRef, accessToken)
86+
if (tokenCanAccesProject) {
87+
return null
88+
}
89+
90+
// If the token does not return a project then projectRef could be a branch
91+
// project, in which case we enumerate branch projects of all projects
92+
const allProjectRefs = await getAllProjects(accessToken)
93+
for (const ref of allProjectRefs) {
94+
const branches = await getAllBranches(ref, accessToken)
95+
if (branches.includes(projectRef)) {
96+
return null
97+
}
98+
}
99+
100+
// It's not even a branch project
101+
return 'Unauthorized: Invalid credentials'
102+
}
103+
15104
// Helper to delete edge function via Management API
16105
async function deleteEdgeFunction(
17106
projectRef: string,
@@ -74,6 +163,11 @@ Deno.serve(async (req) => {
74163

75164
const accessToken = authHeader.substring(7) // Remove 'Bearer '
76165

166+
const supabaseAuthError = await authenticateWithSupabase(projectRef, accessToken)
167+
if (supabaseAuthError) {
168+
return new Response('Unauthorized', { status: 401 })
169+
}
170+
77171
// Handle GET requests for status
78172
if (req.method === 'GET') {
79173
const dbUrl = Deno.env.get('SUPABASE_DB_URL')

0 commit comments

Comments
 (0)