Skip to content
Open
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
198 changes: 182 additions & 16 deletions installation/authentication-setup/supabase-auth.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -24,37 +24,203 @@

* Experimental: We've also heard from the community that Supabase's newly released [support for external auth providers works](https://supabase.com/blog/third-party-auth-mfa-phone-send-hooks), but we don't have any examples for this yet.

## Enabling Supabase Auth
## Supabase JWT Signing Keys

To implement either **Supabase Auth** or **Anonymous Sign-Ins**, enable the relevant setting on the PowerSync instance, and provide your Supabase JWT Secret. Internally, this setting allows PowerSync to verify and use Supabase JWTs directly using HS256 and the provided secret.
Supabase supports two types of JWT signing keys:

### PowerSync Cloud instances:
| Type | Algorithm | Description |
|------|-----------|-------------|
| **Legacy JWT signing keys** | HS256 (symmetric) | Uses a shared secret to sign and verify tokens. This is the original method. |
| **New JWT signing keys** | RS256 (asymmetric) | Uses public/private key pairs. Supabase signs tokens with a private key, and PowerSync verifies them using a public key fetched via JWKS. |

1. In the [PowerSync Dashboard](https://dashboard.powersync.com/), select your project and instance and go to the **Client Auth** view.
PowerSync supports both methods. Which configuration you need depends on your Supabase project's JWT settings and your PowerSync deployment type.

2. Enable the **"Use Supabase Auth"** checkbox.
<Note>
To check which signing keys your Supabase project uses, go to [Project Settings > JWT](https://supabase.com/dashboard/project/_/settings/jwt) in your Supabase Dashboard.
</Note>

## PowerSync Cloud

When using PowerSync Cloud with a Supabase-hosted database, PowerSync can auto-detect your Supabase project from the database connection string and configure authentication automatically.

<Tabs>
<Tab title="New JWT Signing Keys (Recommended)">
### Using New JWT Signing Keys

This is the recommended approach for Supabase projects using asymmetric JWT signing keys.

1. In the [PowerSync Dashboard](https://dashboard.powersync.com/), select your project and instance and go to the **Client Auth** view.

2. **Enable** the **"Use Supabase Auth"** checkbox.

3. Leave the **"Supabase JWT Secret"** field empty (it's not needed for new keys).

4. Click **Save and Deploy**.

<Info>
PowerSync auto-detects your Supabase project from the database connection string and configures the JWKS URI (`https://<project-ref>.supabase.co/auth/v1/.well-known/jwks.json`) and audience (`authenticated`) automatically.
</Info>
</Tab>

<Tab title="Legacy JWT Signing Keys">
### Using Legacy JWT Signing Keys

Use this approach if your Supabase project still uses the legacy HS256 symmetric signing keys.

1. In the [PowerSync Dashboard](https://dashboard.powersync.com/), select your project and instance and go to the **Client Auth** view.

2. **Enable** the **"Use Supabase Auth"** checkbox.

3. Copy your **JWT Secret** from your Supabase project's [JWT settings](https://supabase.com/dashboard/project/_/settings/jwt).

4. Paste the secret into the **"Supabase JWT Secret (optional) Legacy"** field.

5. Click **Save and Deploy**.
</Tab>

<Tab title="Manual JWKS Configuration">
### Manual JWKS Configuration

Use manual configuration when PowerSync cannot auto-detect your Supabase project. This happens when:
- You're using a non-standard database connection string
- You're connecting to a self-hosted Supabase instance
- You're using Supabase local development (Docker)

1. In the [PowerSync Dashboard](https://dashboard.powersync.com/), go to the **Client Auth** view.

2. Leave the **"Use Supabase Auth"** checkbox **unchecked**.

3. Add a **JWKS URI**:
```
http://localhost:54321/auth/v1/.well-known/jwks.json
```
Replace `<your-project-ref>` with your Supabase project reference ID.

4. Add `authenticated` as an accepted **JWT audience**.

5. Click **Save and Deploy**.

<Warning>
If you skip adding the `authenticated` audience, you will see `PSYNC_S2105` errors ("JWT payload is missing a required claim 'aud'").
</Warning>
</Tab>
</Tabs>

## Self-Hosted PowerSync

For self-hosted PowerSync instances, configure authentication in your [`config.yaml`](/self-hosting/installation/powersync-service-setup#powersync-configuration).

3. Copy your JWT Secret from your Supabase project's settings ([JWT Keys](https://supabase.com/dashboard/project/_/settings/jwt) section in the Supabase dashboard).
<Tabs>
<Tab title="New JWT Signing Keys (Recommended)">
### Using New JWT Signing Keys

4. If your Supabase project uses the legacy JWT signing keys, paste the secret into the **"Supabase JWT Secret (optional) Legacy"** field. If you're using Supabase's new JWT signing keys, you can leave this field empty.
When using a standard Supabase connection string, PowerSync auto-detects your Supabase project:

5. Click **Save and Deploy** to apply the changes.
```yaml
client_auth:
supabase: true
```

PowerSync will automatically configure:
- **JWKS URI**: `https://<project-ref>.supabase.co/auth/v1/.well-known/jwks.json`
- **Audience**: `authenticated`

You'll see a log message confirming the configuration:
```
Configured Supabase Auth with https://<project-ref>.supabase.co/auth/v1/.well-known/jwks.json
```
</Tab>

<Tab title="Legacy JWT Signing Keys">
### Using Legacy JWT Signing Keys

For projects using legacy HS256 symmetric signing keys, provide your JWT secret:

```yaml
client_auth:
supabase: true
supabase_jwt_secret: your-jwt-secret-here
```

Get your JWT secret from your Supabase project's [JWT settings](https://supabase.com/dashboard/project/_/settings/jwt).
</Tab>

<Tab title="Manual JWKS Configuration">
### Manual JWKS Configuration

Use manual configuration when:
- PowerSync cannot detect your Supabase project from the connection string
- You're using self-hosted Supabase
- You're using Supabase local development (Docker)
- You need explicit control over the authentication settings

```yaml
client_auth:
jwks_uri: http://localhost:54321/auth/v1/.well-known/jwks.json
audience:
- authenticated
```

Replace `<your-project-ref>` with your Supabase project reference ID.

<Note>
PowerSync is compatible with Supabase's new [JWT signing keys](https://supabase.com/blog/jwt-signing-keys). If you're using the new keys, you don't need to provide the legacy JWT secret. See this [Discord thread](https://discord.com/channels/1138230179878154300/1194710422960472175/1396878076683485205) for details.
When using manual configuration, do not set `supabase: true`. Use `jwks_uri` and `audience` directly.
</Note>
</Tab>
</Tabs>

## Migrating from Legacy to New JWT Signing Keys

If you're migrating your Supabase project from legacy JWT signing keys to the new asymmetric keys:

### Step 1: Complete the Supabase Migration

Follow **all steps** in [Supabase's JWT Signing Keys migration guide](https://supabase.com/blog/jwt-signing-keys#start-using-asymmetric-jwts-today), including the **"Rotate to asymmetric JWTs"** step.

### Self-hosted instances:
<Warning>
The migration is not complete until you complete the "Rotate to asymmetric JWTs" step in Supabase. Skipping this step will cause authentication failures.
</Warning>

This can be enabled via your [`config.yaml`](/self-hosting/installation/powersync-service-setup):
### Step 2: Update PowerSync Configuration

```yaml
client_auth:
# Enable this if using Supabase Auth*
supabase: true
supabase_jwt_secret: your-jwt-secret
**For PowerSync Cloud and self-hosted with standard Supabase connections:**
- No changes required, PowerSync auto-detects and uses the new JWKS endpoint.
- If you previously provided a legacy JWT secret, you can remove it (it's no longer needed).

**For manual JWKS configurations:**
- Ensure your `jwks_uri` points to your Supabase JWKS endpoint.
- Verify the `authenticated` audience is configured.

### Step 3: Clear Cached Tokens

Have all users sign out and sign back in. This ensures they receive new tokens signed with the asymmetric keys.

## Troubleshooting

### PSYNC_S2101: Could not find an appropriate key in the keystore

Check warning on line 200 in installation/authentication-setup/supabase-auth.mdx

View check run for this annotation

Mintlify / Mintlify Validation (powersync) - vale-spellcheck

installation/authentication-setup/supabase-auth.mdx#L200

Did you really mean 'keystore'?

This error indicates PowerSync cannot verify the JWT signature. Common causes:

| Cause | Solution |
|-------|----------|
| **Incomplete Supabase migration** | Complete the "Rotate to asymmetric JWTs" step in Supabase's migration guide. |
| **Cached tokens** | Have users sign out and sign back in to get fresh tokens. |
| **Non-standard connection string** | PowerSync couldn't auto-detect your Supabase project. Use [manual JWKS configuration](#manual-jwks-configuration). |
| **Wrong JWT secret** | For legacy keys, verify the JWT secret matches your Supabase project settings. |

### PSYNC_S2105: JWT payload is missing a required claim "aud"

This error occurs when using manual JWKS configuration without specifying an audience. Add `authenticated` to your audience configuration.

### Auto-detection not working

If PowerSync logs this warning:
```
Supabase Auth is enabled, but no Supabase connection string found. Skipping Supabase JWKS URL configuration.
```

This means PowerSync couldn't detect your Supabase project from the database connection string. Use [manual JWKS configuration](#manual-jwks-configuration) instead.

## Sync Rules

The Supabase user UUID will be available as `request.user_id()` in [Sync Rules](/usage/sync-rules). To use a different identifier as the user ID in Sync Rules (for example user email), use [Custom authentication](/installation/authentication-setup/custom).
5 changes: 5 additions & 0 deletions resources/troubleshooting/error-codes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

This reference documents PowerSync error codes organized by component, with troubleshooting suggestions for developers. Use the search bar to look up specific error codes (e.g., `PSYNC_R0001`).

# PSYNC_Rxxxx: Sync rules issues

Check warning on line 9 in resources/troubleshooting/error-codes.mdx

View check run for this annotation

Mintlify / Mintlify Validation (powersync) - vale-spellcheck

resources/troubleshooting/error-codes.mdx#L9

Did you really mean 'PSYNC_Rxxxx'?

- **PSYNC_R0001**:
Catch-all sync rules parsing error, if no more specific error is available
Expand All @@ -23,7 +23,7 @@

## PSYNC_R24xx: SQL security warnings

# PSYNC_Sxxxx: Service issues

Check warning on line 26 in resources/troubleshooting/error-codes.mdx

View check run for this annotation

Mintlify / Mintlify Validation (powersync) - vale-spellcheck

resources/troubleshooting/error-codes.mdx#L26

Did you really mean 'PSYNC_Sxxxx'?

- **PSYNC_S0001**:
Internal assertion.
Expand Down Expand Up @@ -121,7 +121,7 @@
Create a publication using `WITH (publish = "insert, update, delete, truncate")` (the default).

- **PSYNC_S1143**:
Publication uses publish_via_partition_root.

Check warning on line 124 in resources/troubleshooting/error-codes.mdx

View check run for this annotation

Mintlify / Mintlify Validation (powersync) - vale-spellcheck

resources/troubleshooting/error-codes.mdx#L124

Did you really mean 'publish_via_partition_root'?

- **PSYNC_S1144**:
Invalid Postgres server configuration for replication and sync bucket storage.
Expand Down Expand Up @@ -188,7 +188,7 @@
The MongoDB Change Stream has been invalidated.

Possible causes:
- Some change stream documents do not have postImages.

Check warning on line 191 in resources/troubleshooting/error-codes.mdx

View check run for this annotation

Mintlify / Mintlify Validation (powersync) - vale-spellcheck

resources/troubleshooting/error-codes.mdx#L191

Did you really mean 'postImages'?
- startAfter/resumeToken is not valid anymore.
- The replication connection has changed.
- The database has been dropped.
Expand Down Expand Up @@ -239,12 +239,17 @@
- **PSYNC_S2101**:
Generic authentication error.

Common causes:
1. **JWT signing key mismatch** (Supabase): The client is using tokens signed with a different key type (legacy vs. new JWT signing keys) than PowerSync expects. If you've migrated to new JWT signing keys, ensure users sign out and back in to get fresh tokens. See [Migrating from Legacy to New JWT Signing Keys](/installation/authentication-setup/supabase-auth#migrating-from-legacy-to-new-jwt-signing-keys).
2. **Missing or invalid key ID (kid)**: The token's kid header doesn't match any keys in PowerSync's keystore.

Check warning on line 244 in resources/troubleshooting/error-codes.mdx

View check run for this annotation

Mintlify / Mintlify Validation (powersync) - vale-spellcheck

resources/troubleshooting/error-codes.mdx#L244

Did you really mean 'keystore'?
3. **Incorrect JWT secret or JWKS endpoint**: Verify your authentication configuration matches your auth provider's settings.

- **PSYNC_S2102**:
Could not verify the auth token signature.

Typical causes include:
1. Token kid is not found in the keystore.

Check warning on line 251 in resources/troubleshooting/error-codes.mdx

View check run for this annotation

Mintlify / Mintlify Validation (powersync) - vale-spellcheck

resources/troubleshooting/error-codes.mdx#L251

Did you really mean 'keystore'?
2. Signature does not match the kid in the keystore.

Check warning on line 252 in resources/troubleshooting/error-codes.mdx

View check run for this annotation

Mintlify / Mintlify Validation (powersync) - vale-spellcheck

resources/troubleshooting/error-codes.mdx#L252

Did you really mean 'keystore'?

- **PSYNC_S2103**:
Token has expired. Check the expiry date on the token.
Expand Down