Skip to content

Commit 38fd0c1

Browse files
authored
ENG-925 Upgrade supabase JWT keys (#752)
1 parent dffb849 commit 38fd0c1

14 files changed

Lines changed: 98 additions & 28 deletions

File tree

apps/obsidian/scripts/compile.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,8 @@ export const compile = ({
123123
"process.env.SUPABASE_URL": dbEnv.SUPABASE_URL
124124
? `"${dbEnv.SUPABASE_URL}"`
125125
: "null",
126-
"process.env.SUPABASE_ANON_KEY": dbEnv.SUPABASE_ANON_KEY
127-
? `"${dbEnv.SUPABASE_ANON_KEY}"`
126+
"process.env.SUPABASE_PUBLISHABLE_KEY": dbEnv.SUPABASE_PUBLISHABLE_KEY
127+
? `"${dbEnv.SUPABASE_PUBLISHABLE_KEY}"`
128128
: "null",
129129
"process.env.NEXT_API_ROOT": `"${dbEnv.NEXT_API_ROOT || ""}"`,
130130
},

apps/roam/scripts/compile.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,8 @@ export const compile = ({
162162
"process.env.SUPABASE_URL": dbEnv.SUPABASE_URL
163163
? `"${dbEnv.SUPABASE_URL}"`
164164
: "null",
165-
"process.env.SUPABASE_ANON_KEY": dbEnv.SUPABASE_ANON_KEY
166-
? `"${dbEnv.SUPABASE_ANON_KEY}"`
165+
"process.env.SUPABASE_PUBLISHABLE_KEY": dbEnv.SUPABASE_PUBLISHABLE_KEY
166+
? `"${dbEnv.SUPABASE_PUBLISHABLE_KEY}"`
167167
: "null",
168168
"process.env.NEXT_API_ROOT": `"${dbEnv.NEXT_API_ROOT || ""}"`,
169169
"window.__DISCOURSE_GRAPH_VERSION__": `"${getVersion()}"`,

apps/website/app/api/supabase/env/route.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@ import {
66

77
export const GET = (request: NextRequest): NextResponse => {
88
try {
9-
const { SUPABASE_URL, SUPABASE_ANON_KEY } = process.env;
10-
if (!SUPABASE_URL || !SUPABASE_ANON_KEY)
9+
const { SUPABASE_URL, SUPABASE_ANON_KEY, SUPABASE_PUBLISHABLE_KEY } =
10+
process.env;
11+
if (!SUPABASE_URL || !SUPABASE_PUBLISHABLE_KEY)
1112
return new NextResponse("Missing variables", { status: 500 });
1213
return NextResponse.json(
1314
// eslint-disable-next-line @typescript-eslint/naming-convention
14-
{ SUPABASE_URL, SUPABASE_ANON_KEY },
15+
{ SUPABASE_URL, SUPABASE_ANON_KEY, SUPABASE_PUBLISHABLE_KEY },
1516
{ status: 200 },
1617
);
1718
} catch (e: unknown) {

apps/website/app/utils/supabase/middleware.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { envContents } from "@repo/database/dbDotEnv";
1010
export const updateSession = async (request: NextRequest) => {
1111
const dbEnv = envContents();
1212
const supabaseUrl = dbEnv.SUPABASE_URL;
13-
const supabaseKey = dbEnv.SUPABASE_ANON_KEY;
13+
const supabaseKey = dbEnv.SUPABASE_PUBLISHABLE_KEY;
1414

1515
if (!supabaseUrl || !supabaseKey) {
1616
throw new Error("Missing required Supabase environment variables");

apps/website/app/utils/supabase/server.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export const createClient = async () => {
1010
const dbEnv = envContents();
1111
const cookieStore = await cookies();
1212
const supabaseUrl = dbEnv.SUPABASE_URL;
13-
const supabaseKey = dbEnv.SUPABASE_ANON_KEY;
13+
const supabaseKey = dbEnv.SUPABASE_PUBLISHABLE_KEY;
1414

1515
if (!supabaseUrl || !supabaseKey) {
1616
throw new Error("Missing required Supabase environment variables");

packages/database/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,11 @@ This should be used with extreme caution, as there is not currently adequate sec
9898
It may be appropriate if there is a problem in production that is due to corrupted data (vs schema issues), and it is somehow simpler to test code to repair it directly than to load the data locally.
9999
Again, if all your code is running through Vercel API endpoints, the simplest way is to set `NEXT_API_ROOT` to the url of the API of the production Vercel branch (`https://discoursegraphs.com/api`).
100100
But in most other cases, you will want your code to talk to the production database. set up vercel as above, and set `SUPABASE_USE_DB=production` in your console before running `turbo dev`.
101+
102+
## JWT token management
103+
104+
We are now using JWT Signing keys. See the Supabase [announcement](https://github.com/supabase/supabase/blob/037e5f90a5689c3d847bd2adf9c8ec3956a0e7a0/apps/docs/content/guides/functions/auth.mdx) and [documentation](https://supabase.com/docs/guides/auth/signing-keys).
105+
106+
This allows for better key management in general, including key deprecation. One small downside is that the value of `SUPABASE_PUBLISHABLE_KEY` and `SUPABASE_SECRET_KEY`, generated in `https://supabase.com/dashboard/project/<project>/settings/jwt` has to be manually transferred into the edge function secrets, under slightly different names (since the `SUPABASE_` prefix is reserved, we replace it with `SB_`.) This is done in `https://supabase.com/dashboard/project/<project>/functions/secrets`. The announcement says this may get automated at some point.
107+
108+
We also need to transfer the `SUPABASE_PUBLISHABLE_KEY` to github secrets (without rename.) The vercel environment gets updated automaticaly.

packages/database/features/step-definitions/stepdefs.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,14 @@ if (getVariant() === "production") {
2828
config();
2929

3030
const getAnonymousClient = () => {
31-
if (!process.env.SUPABASE_URL || !process.env.SUPABASE_ANON_KEY) {
31+
if (!process.env.SUPABASE_URL || !process.env.SUPABASE_PUBLISHABLE_KEY) {
3232
throw new Error(
33-
"Missing required environment variables: SUPABASE_URL and SUPABASE_ANON_KEY",
33+
"Missing required environment variables: SUPABASE_URL and SUPABASE_PUBLISHABLE_KEY",
3434
);
3535
}
3636
return createClient<Database, "public">(
3737
process.env.SUPABASE_URL,
38-
process.env.SUPABASE_ANON_KEY,
38+
process.env.SUPABASE_PUBLISHABLE_KEY,
3939
);
4040
};
4141

packages/database/scripts/createEnv.mts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { execSync } from "node:child_process";
2-
import { appendFileSync, writeFileSync } from "node:fs";
2+
import { appendFileSync, writeFileSync, readFileSync } from "node:fs";
33
import { join, dirname } from "node:path";
44
import { fileURLToPath } from "node:url";
55
import dotenv from "dotenv";
@@ -28,6 +28,10 @@ const getVercelToken = () => {
2828
return process.env["VERCEL_TOKEN"];
2929
};
3030

31+
const makeFnEnv = (envTxt: string): string => {
32+
return envTxt.split('\n').filter(l=>l.match(/^SUPABASE_\w+_KEY/)).map((l)=> l.replace('SUPABASE_', 'SB_')).join('\n');
33+
}
34+
3135
const makeLocalEnv = () => {
3236
execSync("supabase start", {
3337
cwd: projectRoot, stdio: "inherit"
@@ -48,6 +52,10 @@ const makeLocalEnv = () => {
4852
join(projectRoot, ".env.local"),
4953
prefixed + '\nNEXT_API_ROOT="http://localhost:3000/api"\n',
5054
);
55+
writeFileSync(
56+
join(projectRoot, "supabase/functions/.env"),
57+
makeFnEnv(prefixed)
58+
)
5159
};
5260

5361
const makeBranchEnv = async (vercel: Vercel, vercelToken: string) => {
@@ -86,6 +94,11 @@ const makeBranchEnv = async (vercel: Vercel, vercelToken: string) => {
8694
throw err;
8795
}
8896
appendFileSync(".env.branch", `NEXT_API_ROOT="https://${url}/api"\n`);
97+
const fromVercel = readFileSync('.env.branch').toString();
98+
writeFileSync(
99+
join(projectRoot, "supabase/functions/.env"),
100+
makeFnEnv(fromVercel)
101+
)
89102
};
90103

91104
const makeProductionEnv = async (vercel: Vercel, vercelToken: string) => {
@@ -104,6 +117,11 @@ const makeProductionEnv = async (vercel: Vercel, vercelToken: string) => {
104117
`vercel -t ${vercelToken} env pull --environment production .env.production`,
105118
);
106119
appendFileSync(".env.production", `NEXT_API_ROOT="https://${url}/api"\n`);
120+
const fromVercel = readFileSync('.env.production').toString();
121+
writeFileSync(
122+
join(projectRoot, "supabase/functions/.env"),
123+
makeFnEnv(fromVercel)
124+
)
107125
};
108126

109127
const main = async (variant: Variant) => {
@@ -118,7 +136,7 @@ const main = async (variant: Variant) => {
118136
);
119137
return;
120138
} catch (e) {
121-
if (process.env.SUPABASE_URL && process.env.SUPABASE_ANON_KEY)
139+
if (process.env.SUPABASE_URL && process.env.SUPABASE_PUBLISHABLE_KEY)
122140
return;
123141
throw new Error("Could not get environment from site");
124142
}

packages/database/src/dbDotEnv.mjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export const getVariant = () => {
2929
variant = process.env["SUPABASE_USE_DB"];
3030
}
3131
const processHasVars =
32-
!!process.env["SUPABASE_URL"] && !!process.env["SUPABASE_ANON_KEY"];
32+
!!process.env["SUPABASE_URL"] && !!process.env["SUPABASE_PUBLISHABLE_KEY"];
3333

3434
if (
3535
["local", "branch", "production", "none", "implicit", undefined].indexOf(
@@ -77,7 +77,7 @@ export const envContents = () => {
7777
// Fallback to process.env when running in production environments
7878
const raw = {
7979
SUPABASE_URL: process.env.SUPABASE_URL,
80-
SUPABASE_ANON_KEY: process.env.SUPABASE_ANON_KEY,
80+
SUPABASE_PUBLISHABLE_KEY: process.env.SUPABASE_PUBLISHABLE_KEY,
8181
NEXT_API_ROOT: process.env.NEXT_API_ROOT,
8282
};
8383
return Object.fromEntries(Object.entries(raw).filter(([, v]) => !!v));

packages/database/src/lib/contextFunctions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ let lastStorageKey: string | undefined = undefined;
9090
// to ensure we never have conflict between multiple clients
9191
const createSingletonClient = (uniqueKey: string): DGSupabaseClient | null => {
9292
const url = process.env.SUPABASE_URL;
93-
const key = process.env.SUPABASE_ANON_KEY;
93+
const key = process.env.SUPABASE_PUBLISHABLE_KEY;
9494

9595
if (!url || !key) {
9696
throw new FatalError("Missing required Supabase environment variables");

0 commit comments

Comments
 (0)