Skip to content

Commit e0c6e0e

Browse files
authored
feat: support Supabase CLI v2+ opaque API keys in local environment detection (#578)
# Add support for Supabase CLI v2+ opaque API keys in local environment detection This PR adds support for detecting local Supabase environments that use the new opaque API keys format introduced in Supabase CLI v2+. The edge worker can now recognize both: - The original HS256 JWT keys (from Supabase CLI v1) - The new opaque keys format (from Supabase CLI v2+) The implementation: - Adds constants for the new publishable and secret keys - Updates the `isLocalSupabaseEnv` function to check for both key formats - Adds comprehensive tests for all key combinations This ensures compatibility with both older and newer Supabase CLI versions when running in local development environments.
1 parent 80a3a68 commit e0c6e0e

3 files changed

Lines changed: 76 additions & 2 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@pgflow/edge-worker': patch
3+
---
4+
5+
Add support for new Supabase CLI v2+ opaque API keys in local environment detection
Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,31 @@
1+
// Old HS256 JWT keys (Supabase CLI v1)
12
export const KNOWN_LOCAL_ANON_KEY =
23
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0';
34

45
export const KNOWN_LOCAL_SERVICE_ROLE_KEY =
56
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImV4cCI6MTk4MzgxMjk5Nn0.EGIM96RAZx35lJzdJsyH-qQwv8Hdp7fsn3W0YpN81IU';
67

8+
// New opaque keys (Supabase CLI v2+)
9+
// Source: https://github.com/supabase/cli/blob/develop/pkg/config/apikeys.go
10+
export const KNOWN_LOCAL_PUBLISHABLE_KEY =
11+
'sb_publishable_ACJWlzQHlZjBrEguHvfOxg_3BJgxAaH';
12+
13+
export const KNOWN_LOCAL_SECRET_KEY = 'sb_secret_N7UND0UgjKTVK-Uodkm0Hg_xSvEMPvz';
14+
715
/**
816
* Checks if the provided environment indicates local Supabase.
917
* Use when you have access to an env record (e.g., from PlatformAdapter).
18+
* Supports both old HS256 JWT keys and new opaque keys from Supabase CLI v2+.
1019
*/
1120
export function isLocalSupabaseEnv(env: Record<string, string | undefined>): boolean {
1221
const anonKey = env['SUPABASE_ANON_KEY'];
1322
const serviceRoleKey = env['SUPABASE_SERVICE_ROLE_KEY'];
14-
return anonKey === KNOWN_LOCAL_ANON_KEY ||
15-
serviceRoleKey === KNOWN_LOCAL_SERVICE_ROLE_KEY;
23+
24+
const isLocalAnonKey =
25+
anonKey === KNOWN_LOCAL_ANON_KEY || anonKey === KNOWN_LOCAL_PUBLISHABLE_KEY;
26+
const isLocalServiceRoleKey =
27+
serviceRoleKey === KNOWN_LOCAL_SERVICE_ROLE_KEY ||
28+
serviceRoleKey === KNOWN_LOCAL_SECRET_KEY;
29+
30+
return isLocalAnonKey || isLocalServiceRoleKey;
1631
}

pkgs/edge-worker/tests/unit/shared/localDetection.test.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import {
33
isLocalSupabaseEnv,
44
KNOWN_LOCAL_ANON_KEY,
55
KNOWN_LOCAL_SERVICE_ROLE_KEY,
6+
KNOWN_LOCAL_PUBLISHABLE_KEY,
7+
KNOWN_LOCAL_SECRET_KEY,
68
} from '../../../src/shared/localDetection.ts';
79

810
// ============================================================
@@ -23,6 +25,20 @@ Deno.test('KNOWN_LOCAL_SERVICE_ROLE_KEY - matches expected value', () => {
2325
);
2426
});
2527

28+
Deno.test('KNOWN_LOCAL_PUBLISHABLE_KEY - matches expected value', () => {
29+
assertEquals(
30+
KNOWN_LOCAL_PUBLISHABLE_KEY,
31+
'sb_publishable_ACJWlzQHlZjBrEguHvfOxg_3BJgxAaH'
32+
);
33+
});
34+
35+
Deno.test('KNOWN_LOCAL_SECRET_KEY - matches expected value', () => {
36+
assertEquals(
37+
KNOWN_LOCAL_SECRET_KEY,
38+
'sb_secret_N7UND0UgjKTVK-Uodkm0Hg_xSvEMPvz'
39+
);
40+
});
41+
2642
// ============================================================
2743
// isLocalSupabaseEnv() tests
2844
// ============================================================
@@ -80,3 +96,41 @@ Deno.test('isLocalSupabaseEnv - returns true when only service role matches (ano
8096
};
8197
assertEquals(isLocalSupabaseEnv(env), true);
8298
});
99+
100+
// ============================================================
101+
// New opaque key tests (Supabase CLI v2+)
102+
// ============================================================
103+
104+
Deno.test('isLocalSupabaseEnv - returns true when anon key matches new publishable key', () => {
105+
const env = { SUPABASE_ANON_KEY: KNOWN_LOCAL_PUBLISHABLE_KEY };
106+
assertEquals(isLocalSupabaseEnv(env), true);
107+
});
108+
109+
Deno.test('isLocalSupabaseEnv - returns true when service role matches new secret key', () => {
110+
const env = { SUPABASE_SERVICE_ROLE_KEY: KNOWN_LOCAL_SECRET_KEY };
111+
assertEquals(isLocalSupabaseEnv(env), true);
112+
});
113+
114+
Deno.test('isLocalSupabaseEnv - returns true when both new opaque keys match', () => {
115+
const env = {
116+
SUPABASE_ANON_KEY: KNOWN_LOCAL_PUBLISHABLE_KEY,
117+
SUPABASE_SERVICE_ROLE_KEY: KNOWN_LOCAL_SECRET_KEY,
118+
};
119+
assertEquals(isLocalSupabaseEnv(env), true);
120+
});
121+
122+
Deno.test('isLocalSupabaseEnv - returns true when mixing old JWT anon with new secret key', () => {
123+
const env = {
124+
SUPABASE_ANON_KEY: KNOWN_LOCAL_ANON_KEY,
125+
SUPABASE_SERVICE_ROLE_KEY: KNOWN_LOCAL_SECRET_KEY,
126+
};
127+
assertEquals(isLocalSupabaseEnv(env), true);
128+
});
129+
130+
Deno.test('isLocalSupabaseEnv - returns true when mixing new publishable with old JWT service role', () => {
131+
const env = {
132+
SUPABASE_ANON_KEY: KNOWN_LOCAL_PUBLISHABLE_KEY,
133+
SUPABASE_SERVICE_ROLE_KEY: KNOWN_LOCAL_SERVICE_ROLE_KEY,
134+
};
135+
assertEquals(isLocalSupabaseEnv(env), true);
136+
});

0 commit comments

Comments
 (0)