From da9ec1a1f048123062500a1149a864bf91ae5033 Mon Sep 17 00:00:00 2001 From: D-K-P <8297864+D-K-P@users.noreply.github.com> Date: Fri, 28 Mar 2025 11:30:25 +0000 Subject: [PATCH 1/3] Added supabase auth page --- docs/docs.json | 3 +- .../frameworks/supabase-authentication.mdx | 75 +++++++++++++++++++ 2 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 docs/guides/frameworks/supabase-authentication.mdx diff --git a/docs/docs.json b/docs/docs.json index b1bb940224..ec7fe64d42 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -281,7 +281,8 @@ "pages": [ "guides/frameworks/supabase-guides-overview", "guides/frameworks/supabase-edge-functions-basic", - "guides/frameworks/supabase-edge-functions-database-webhooks" + "guides/frameworks/supabase-edge-functions-database-webhooks", + "guides/frameworks/supabase-authentication" ] }, { diff --git a/docs/guides/frameworks/supabase-authentication.mdx b/docs/guides/frameworks/supabase-authentication.mdx new file mode 100644 index 0000000000..2efa572e57 --- /dev/null +++ b/docs/guides/frameworks/supabase-authentication.mdx @@ -0,0 +1,75 @@ +--- +title: "Authenticating Supabase tasks: JWTs and service roles" +sidebarTitle: "Supabase authentication" +description: "Learn how to authenticate Supabase tasks using JWTs for Row Level Security (RLS) or service role keys for admin access." +--- + +import SupabaseDocsCards from "/snippets/supabase-docs-cards.mdx"; + +There are two ways to authenticate your Supabase client in Trigger.dev tasks: + +### 1. Using JWT Authentication (Recommended for User-Specific Operations) + +A JWT (JSON Web Token) is a string-formatted data container that typically stores user identity and permissions data. Row Level Security policies are based on the information present in JWTs. Supabase JWT docs can be found [here](https://supabase.com/docs/guides/auth/jwts). + +To use JWTs with Supabase, you'll need to add the `SUPABASE_JWT_SECRET` environment variable in your project. This secret is used to sign the JWTs. This can be found in your Supabase project settings under `Data API`. + +This example code shows how to create a JWT token for a user and initialize a Supabase client with that token for authentication, allowing the task to perform database operations as that specific user. You can adapt this code to fit your own use case. + +```ts + +// The rest of your task code +async run(payload: { user_id: string }) { + const { user_id } = payload; + + // Optional error handling + const jwtSecret = process.env.SUPABASE_JWT_SECRET; + if (!jwtSecret) { + throw new Error( + "SUPABASE_JWT_SECRET is not defined in environment variables" + ); + } + + // Create a JWT token for the user that expires in 1 hour + const token = jwt.sign({ sub: user_id }, jwtSecret, { expiresIn: "1h" }); + + // Initialize the Supabase client with the JWT token + const supabase = createClient( + // These details can be found in your Supabase project settings under `Data API` + process.env.SUPABASE_URL as string, + process.env.SUPABASE_ANON_KEY as string, + { + global: { + headers: { + Authorization: `Bearer ${token}`, + }, + }, + } + ); +// The rest of your task code +``` + +Using JWTs to authenticate Supabase operations is more secure than using service role keys because it respects Row Level Security policies, maintains user-specific audit trails, and follows the principle of least privileged access. + +### 2. Using Service Role Key (For Admin-Level Access) + + + The service role key has unlimited access and bypasses all security checks. Only use it when you + need admin-level privileges, and never expose it client-side. + + +This example code creates a Supabase client with admin-level privileges using a service role key, bypassing all Row Level Security policies to allow unrestricted database access. + +```ts +// Create a single Supabase client for interacting with your database +// 'Database' supplies the type definitions to supabase-js +const supabase = createClient( + // These details can be found in your Supabase project settings under `API` + process.env.SUPABASE_PROJECT_URL as string, // e.g. https://abc123.supabase.co - replace 'abc123' with your project ID + process.env.SUPABASE_SERVICE_ROLE_KEY as string // Your service role secret key +); + +// Your task +``` + + From ea9026856e1e32cc16b7c000ae70bebb64a1daac Mon Sep 17 00:00:00 2001 From: D-K-P <8297864+D-K-P@users.noreply.github.com> Date: Fri, 28 Mar 2025 11:30:32 +0000 Subject: [PATCH 2/3] Added auth info snippet --- docs/snippets/supabase-auth-info.mdx | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 docs/snippets/supabase-auth-info.mdx diff --git a/docs/snippets/supabase-auth-info.mdx b/docs/snippets/supabase-auth-info.mdx new file mode 100644 index 0000000000..a6631afe81 --- /dev/null +++ b/docs/snippets/supabase-auth-info.mdx @@ -0,0 +1,6 @@ + + To learn more about how to properly configure Supabase auth for Trigger.dev tasks, please refer to + our [Supabase Authentication guide](/guides/frameworks/supabase-authentication). It demonstrates + how to use JWT authentication for user-specific operations or your service role key for + admin-level access. + From 0058c5f30b75cd853874353f2e27a9f0446dfb18 Mon Sep 17 00:00:00 2001 From: D-K-P <8297864+D-K-P@users.noreply.github.com> Date: Fri, 28 Mar 2025 11:32:41 +0000 Subject: [PATCH 3/3] Added snippet and updated examples --- .../examples/supabase-database-operations.mdx | 39 ++++++++++++------- .../examples/supabase-storage-upload.mdx | 3 ++ .../supabase-edge-functions-basic.mdx | 11 ++++-- ...abase-edge-functions-database-webhooks.mdx | 14 +++++-- docs/snippets/supabase-docs-cards.mdx | 10 ++++- 5 files changed, 55 insertions(+), 22 deletions(-) diff --git a/docs/guides/examples/supabase-database-operations.mdx b/docs/guides/examples/supabase-database-operations.mdx index 4effb54d32..26796b7b0d 100644 --- a/docs/guides/examples/supabase-database-operations.mdx +++ b/docs/guides/examples/supabase-database-operations.mdx @@ -5,6 +5,7 @@ description: "These examples demonstrate how to run basic CRUD operations on a t --- import SupabaseDocsCards from "/snippets/supabase-docs-cards.mdx"; +import SupabaseAuthInfo from "/snippets/supabase-auth-info.mdx"; ## Add a new user to a table in a Supabase database @@ -27,22 +28,37 @@ This is a basic task which inserts a new row into a table from a Trigger.dev tas ```ts trigger/supabase-database-insert.ts import { createClient } from "@supabase/supabase-js"; import { task } from "@trigger.dev/sdk/v3"; +import jwt from "jsonwebtoken"; // Generate the Typescript types using the Supabase CLI: https://supabase.com/docs/guides/api/rest/generating-types import { Database } from "database.types"; -// Create a single Supabase client for interacting with your database -// 'Database' supplies the type definitions to supabase-js -const supabase = createClient( - // These details can be found in your Supabase project settings under `API` - process.env.SUPABASE_PROJECT_URL as string, // e.g. https://abc123.supabase.co - replace 'abc123' with your project ID - process.env.SUPABASE_SERVICE_ROLE_KEY as string // Your service role secret key -); - export const supabaseDatabaseInsert = task({ id: "add-new-user", run: async (payload: { userId: string }) => { const { userId } = payload; + // Get JWT secret from env vars + const jwtSecret = process.env.SUPABASE_JWT_SECRET; + if (!jwtSecret) { + throw new Error("SUPABASE_JWT_SECRET is not defined in environment variables"); + } + + // Create JWT token for the user + const token = jwt.sign({ sub: userId }, jwtSecret, { expiresIn: "1h" }); + + // Initialize Supabase client with JWT + const supabase = createClient( + process.env.SUPABASE_URL as string, + process.env.SUPABASE_ANON_KEY as string, + { + global: { + headers: { + Authorization: `Bearer ${token}`, + }, + }, + } + ); + // Insert a new row into the user_subscriptions table with the provided userId const { error } = await supabase.from("user_subscriptions").insert({ user_id: userId, @@ -60,12 +76,7 @@ export const supabaseDatabaseInsert = task({ }); ``` - - This task uses your service role secret key to bypass Row Level Security. There are different ways - of configuring your [RLS - policies](https://supabase.com/docs/guides/database/postgres/row-level-security), so always make - sure you have the correct permissions set up for your project. - + ### Testing your task diff --git a/docs/guides/examples/supabase-storage-upload.mdx b/docs/guides/examples/supabase-storage-upload.mdx index 4ae98495ff..a4c91d7e7c 100644 --- a/docs/guides/examples/supabase-storage-upload.mdx +++ b/docs/guides/examples/supabase-storage-upload.mdx @@ -5,6 +5,7 @@ description: "This example demonstrates how to upload files to Supabase Storage --- import SupabaseDocsCards from "/snippets/supabase-docs-cards.mdx"; +import SupabaseAuthInfo from "/snippets/supabase-auth-info.mdx"; ## Overview @@ -137,6 +138,8 @@ export const supabaseStorageUploadS3 = task({ }); ``` + + ### Testing your task To test this task in the dashboard, you can use the following payload: diff --git a/docs/guides/frameworks/supabase-edge-functions-basic.mdx b/docs/guides/frameworks/supabase-edge-functions-basic.mdx index 7b00f176bb..f848f05000 100644 --- a/docs/guides/frameworks/supabase-edge-functions-basic.mdx +++ b/docs/guides/frameworks/supabase-edge-functions-basic.mdx @@ -17,6 +17,8 @@ import NextjsTroubleshootingButtonSyntax from "/snippets/nextjs-button-syntax.md import WorkerFailedToStartWhenRunningDevCommand from "/snippets/worker-failed-to-start.mdx"; import SupabaseDocsCards from "/snippets/supabase-docs-cards.mdx"; +import SupabaseAuthInfo from "/snippets/supabase-auth-info.mdx"; + ## Overview Supabase edge functions allow you to trigger tasks either when an event is sent from a third party (e.g. when a new Stripe payment is processed, when a new user signs up to a service, etc), or when there are any changes or updates to your Supabase database. @@ -109,11 +111,12 @@ You can now deploy your edge function with the following command in your termina supabase functions deploy edge-function-trigger --no-verify-jwt ``` - + `--no-verify-jwt` removes the JSON Web Tokens requirement from the authorization header. By - default this should be on, but it is not required for this example. Learn more about JWTs - [here](https://supabase.com/docs/guides/auth/jwts). - + default this should be on, but it is not strictly required for this hello world example. + + + Follow the CLI instructions and once complete you should now see your new edge function deployment in your Supabase edge functions dashboard. diff --git a/docs/guides/frameworks/supabase-edge-functions-database-webhooks.mdx b/docs/guides/frameworks/supabase-edge-functions-database-webhooks.mdx index d64f058520..71bb59dcd7 100644 --- a/docs/guides/frameworks/supabase-edge-functions-database-webhooks.mdx +++ b/docs/guides/frameworks/supabase-edge-functions-database-webhooks.mdx @@ -12,6 +12,7 @@ import NextjsTroubleshootingMissingApiKey from "/snippets/nextjs-missing-api-key import NextjsTroubleshootingButtonSyntax from "/snippets/nextjs-button-syntax.mdx"; import WorkerFailedToStartWhenRunningDevCommand from "/snippets/worker-failed-to-start.mdx"; import SupabaseDocsCards from "/snippets/supabase-docs-cards.mdx"; +import SupabaseAuthInfo from "/snippets/supabase-auth-info.mdx"; ## Overview @@ -136,6 +137,12 @@ yarn install @deepgram/sdk @supabase/supabase-js fluent-ffmpeg These dependencies will allow you to interact with the Deepgram and Supabase APIs and extract audio from a video using FFmpeg. + + When updating your tables from a Trigger.dev task which has been triggered by a database change, + be extremely careful to not cause an infinite loop. Ensure you have the correct conditions in + place to prevent this. + + ```ts /trigger/videoProcessAndUpdate.ts // Install any missing dependencies below import { createClient as createDeepgramClient } from "@deepgram/sdk"; @@ -235,11 +242,12 @@ export const videoProcessAndUpdate = task({ ``` - When updating your tables from a Trigger.dev task which has been triggered by a database change, - be extremely careful to not cause an infinite loop. Ensure you have the correct conditions in - place to prevent this. + This task uses your service role secret key to bypass Row Level Security. This is not recommended + for production use as it has unlimited access and bypasses all security checks. + + ### Adding the FFmpeg build extension Before you can deploy the task, you'll need to add the FFmpeg build extension to your `trigger.config.ts` file. diff --git a/docs/snippets/supabase-docs-cards.mdx b/docs/snippets/supabase-docs-cards.mdx index a5e7011d3b..e8feb68da0 100644 --- a/docs/snippets/supabase-docs-cards.mdx +++ b/docs/snippets/supabase-docs-cards.mdx @@ -2,7 +2,7 @@ ### Full walkthrough guides from development to deployment - + Learn how to trigger a task from a Supabase edge function when an event occurs in your database. + + Learn how to authenticate Supabase tasks using JWTs for Row Level Security (RLS) or service role + keys for admin access. + ### Task examples with code you can copy and paste