Skip to content

Added supabase auth page and updated examples #1838

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
]
},
{
Expand Down
39 changes: 25 additions & 14 deletions docs/guides/examples/supabase-database-operations.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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<Database>(
// 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<Database>(
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,
Expand All @@ -60,12 +76,7 @@ export const supabaseDatabaseInsert = task({
});
```

<Note>
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.
</Note>
<SupabaseAuthInfo />

### Testing your task

Expand Down
3 changes: 3 additions & 0 deletions docs/guides/examples/supabase-storage-upload.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -137,6 +138,8 @@ export const supabaseStorageUploadS3 = task({
});
```

<SupabaseAuthInfo />

### Testing your task

To test this task in the dashboard, you can use the following payload:
Expand Down
75 changes: 75 additions & 0 deletions docs/guides/frameworks/supabase-authentication.mdx
Original file line number Diff line number Diff line change
@@ -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)

<Warning>
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.
</Warning>

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<Database>(
// 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
```

<SupabaseDocsCards />
11 changes: 7 additions & 4 deletions docs/guides/frameworks/supabase-edge-functions-basic.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
```

<Note>
<Warning>
`--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).
</Note>
default this should be on, but it is not strictly required for this hello world example.
</Warning>

<SupabaseAuthInfo />

Follow the CLI instructions and once complete you should now see your new edge function deployment in your Supabase edge functions dashboard.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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.

<Warning>
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.
</Warning>

```ts /trigger/videoProcessAndUpdate.ts
// Install any missing dependencies below
import { createClient as createDeepgramClient } from "@deepgram/sdk";
Expand Down Expand Up @@ -235,11 +242,12 @@ export const videoProcessAndUpdate = task({
```

<Warning>
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.
</Warning>

<SupabaseAuthInfo />

### 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.
Expand Down
6 changes: 6 additions & 0 deletions docs/snippets/supabase-auth-info.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<Note>
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.
</Note>
10 changes: 9 additions & 1 deletion docs/snippets/supabase-docs-cards.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

### Full walkthrough guides from development to deployment

<CardGroup cols={2}>
<CardGroup cols={1}>
<Card
title="Edge function hello world guide"
icon="book"
Expand All @@ -17,6 +17,14 @@
>
Learn how to trigger a task from a Supabase edge function when an event occurs in your database.
</Card>
<Card
title="Supabase authentication guide"
icon="book"
href="/guides/frameworks/supabase-authentication"
>
Learn how to authenticate Supabase tasks using JWTs for Row Level Security (RLS) or service role
keys for admin access.
</Card>
</CardGroup>

### Task examples with code you can copy and paste
Expand Down