mirror of
https://github.com/supabase/supabase.git
synced 2026-09-08 19:08:44 +08:00
## TL;DR Database webhooks/Cron jobs now add `apikey: <secret-key>` for edge function auth.. ## ref: - related to: https://github.com/supabase/supabase/pull/46890 - towards COM-269 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## New Features * Improved edge function webhook authentication by automatically selecting the appropriate API key or authorization header format. * Authorization headers are now added or normalized when required, while preserving existing custom headers and supported credentials. ## Improvements * Simplified “Add header” and “Add parameter” controls with clearer labels. * Updated authentication actions to clearly describe the selected header type. ## Tests * Expanded coverage for key formats, authorization behavior, header preservation, and revised control labels. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Tomás Pozo <tomaspozo@users.noreply.github.com> Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
85 lines
2.7 KiB
TypeScript
85 lines
2.7 KiB
TypeScript
import type { KeyValueFieldArrayAction } from 'ui-patterns/form/KeyValueFieldArray/KeyValueFieldArray'
|
|
|
|
interface BuildEdgeFunctionHeaderAddActionsParams<TRow> {
|
|
apiKey: string
|
|
createRow: (name: string, value: string) => TRow
|
|
}
|
|
|
|
interface HTTPHeader {
|
|
name: string
|
|
value: string
|
|
}
|
|
|
|
interface EnsureEdgeFunctionAuthorizationHeaderParams<TRow extends HTTPHeader> {
|
|
headers: TRow[]
|
|
serviceRoleKey?: string
|
|
verifyJwt?: boolean
|
|
createRow: (name: string, value: string) => TRow
|
|
}
|
|
|
|
const isNewApiKey = (apiKey: string) =>
|
|
apiKey.startsWith('sb_secret_') || apiKey.startsWith('sb_publishable_')
|
|
|
|
export const getEdgeFunctionAuthHeader = (apiKey: string) =>
|
|
isNewApiKey(apiKey)
|
|
? { name: 'apikey', value: apiKey }
|
|
: { name: 'Authorization', value: `Bearer ${apiKey}` }
|
|
|
|
export const ensureEdgeFunctionAuthorizationHeader = <TRow extends HTTPHeader>({
|
|
headers,
|
|
serviceRoleKey,
|
|
verifyJwt,
|
|
createRow,
|
|
}: EnsureEdgeFunctionAuthorizationHeaderParams<TRow>): TRow[] => {
|
|
if (!verifyJwt || !serviceRoleKey || isNewApiKey(serviceRoleKey)) return headers
|
|
|
|
const isAuthorization = (header: HTTPHeader) =>
|
|
header.name.trim().toLowerCase() === 'authorization'
|
|
const authorizationIndex = headers.findIndex(isAuthorization)
|
|
|
|
if (authorizationIndex === -1) {
|
|
return [...headers, createRow('Authorization', `Bearer ${serviceRoleKey}`)]
|
|
}
|
|
|
|
const authorizationHeader = headers[authorizationIndex]
|
|
const normalizedHeaders = headers.filter(
|
|
(header, index) => index === authorizationIndex || !isAuthorization(header)
|
|
)
|
|
|
|
if (normalizedHeaders.length === headers.length && authorizationHeader.name === 'Authorization') {
|
|
return headers
|
|
}
|
|
|
|
normalizedHeaders[authorizationIndex] = {
|
|
...authorizationHeader,
|
|
name: 'Authorization',
|
|
}
|
|
return normalizedHeaders
|
|
}
|
|
|
|
export const buildEdgeFunctionHeaderAddActions = <TRow>({
|
|
apiKey,
|
|
createRow,
|
|
}: BuildEdgeFunctionHeaderAddActionsParams<TRow>): KeyValueFieldArrayAction<TRow>[] => {
|
|
const authHeader = getEdgeFunctionAuthHeader(apiKey)
|
|
|
|
return [
|
|
{
|
|
key: 'add-auth-header',
|
|
label: 'Add secret key',
|
|
description:
|
|
authHeader.name === 'apikey'
|
|
? 'Requires JWT verification to be disabled and authorization handled by the function'
|
|
: 'Required for edge functions that enforce JWT verification',
|
|
createRows: () => [createRow(authHeader.name, authHeader.value)],
|
|
},
|
|
{
|
|
key: 'add-source-header',
|
|
label: 'Add custom source',
|
|
description: 'Useful to verify that the edge function was triggered from this webhook',
|
|
createRows: () => createRow('x-supabase-webhook-source', '[Use a secret value]'),
|
|
separatorAbove: true,
|
|
},
|
|
]
|
|
}
|