From fc72b394c73176542494de4d56a93787ab06cf19 Mon Sep 17 00:00:00 2001 From: bean1352 Date: Mon, 12 Jan 2026 10:51:25 +0200 Subject: [PATCH 1/4] Added details on using legacy and new JWT signing keys method, including configuration examples and common migration issues. --- .../authentication-setup/supabase-auth.mdx | 96 +++++++++++++++++-- resources/troubleshooting/error-codes.mdx | 5 + 2 files changed, 95 insertions(+), 6 deletions(-) diff --git a/installation/authentication-setup/supabase-auth.mdx b/installation/authentication-setup/supabase-auth.mdx index 679a37a1..7b6a5c60 100644 --- a/installation/authentication-setup/supabase-auth.mdx +++ b/installation/authentication-setup/supabase-auth.mdx @@ -26,35 +26,119 @@ You can implement various types of auth: ## Enabling Supabase Auth -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. +PowerSync can verify Supabase JWTs using either the legacy JWT signing keys or the newer asymmetric JWT signing keys: + +- **Legacy JWT signing keys**: Use the "Use Supabase Auth" checkbox and provide your JWT secret. PowerSync verifies tokens using HS256 symmetric signing. +- **JWT signing keys**: Manually configure JWKS authentication (do not use "Use Supabase Auth"). PowerSync verifies tokens using asymmetric public key cryptography. ### PowerSync Cloud instances: +#### Using Legacy 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. +2. **Enable** the **"Use Supabase Auth"** checkbox. 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). -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. +4. Paste the secret into the **"Supabase JWT Secret (optional) Legacy"** field. 5. Click **Save and Deploy** to apply the changes. +#### Using New JWT Signing Keys + + +"Use Supabase Auth" ONLY works with legacy JWT signing keys. If you're using Supabase's new JWT signing keys, you must use manual JWKS configuration instead. + + +1. In the [PowerSync Dashboard](https://dashboard.powersync.com/), select your project and instance and go to the **Client Auth** view. + +2. **Disable** the **"Use Supabase Auth"** checkbox (or leave it unchecked). + +3. Complete 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 Keys"** step. + +4. Add the custom JWKS URI: + - **JWKS URI**: `https://.supabase.co/auth/v1/.well-known/jwks.json` + - Replace `` with your actual Supabase project reference ID + +5. Add JWT audience: + - Add `authenticated` as an accepted JWT audience + +6. Click **Save and Deploy** to apply the changes. + -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. +See this [Discord thread](https://discord.com/channels/1138230179878154300/1194710422960472175/1396878076683485205) for community discussion about using the new JWT signing keys. ### Self-hosted instances: -This can be enabled via your [`config.yaml`](/self-hosting/installation/powersync-service-setup): +Configure via your [`config.yaml`](/self-hosting/installation/powersync-service-setup): +**For legacy JWT signing keys:** ```yaml client_auth: - # Enable this if using Supabase Auth* supabase: true supabase_jwt_secret: your-jwt-secret ``` +**For new JWT signing keys:** +```yaml +client_auth: + # Do NOT set supabase: true - it only works with legacy keys + jwks_uri: https://.supabase.co/auth/v1/.well-known/jwks.json + audience: + - authenticated +``` + +## Migrating Between JWT Signing Key Types + + +Your JWT configuration must be consistent across your entire stack. If you're migrating between Supabase's legacy JWT signing keys and the new JWT signing keys, ensure all components are updated together. + + +### Migrating from Legacy to New JWT Signing Keys + +To migrate from legacy JWT signing keys to the new asymmetric keys: + +1. **Complete 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) + +2. **Update your PowerSync configuration:** + - **Disable** the **"Use Supabase Auth"** checkbox (it only works with legacy keys) + - Add a custom JWKS URI: `https://.supabase.co/auth/v1/.well-known/jwks.json` + - Add `authenticated` as an accepted JWT audience + - Click **Save and Deploy** + +3. **Update all client applications:** + - Ensure all client apps are using the new Supabase API keys (not legacy keys) + - Update any hardcoded anon keys or service role keys + +4. **Clear cached tokens:** + - Have all users sign out and sign back in + - This ensures they're using tokens generated with the new signing keys + +### Common Migration Issues + +**Error:** `PSYNC_S2101 - Could not find an appropriate key in the keystore` + +This authentication error typically occurs when there's a mismatch between: +- The JWT signing key type used by your client app (legacy vs. new) +- The JWT configuration in your PowerSync instance + +**Common causes:** +1. **Using "Use Supabase Auth" with new JWT signing keys** - This doesn't work. "Use Supabase Auth" ONLY supports legacy keys. +2. **Mismatched client and server keys** - Your client is using legacy keys while PowerSync is configured for new keys (or vice versa). +3. **Incomplete Supabase migration** - You haven't completed the "Rotate Keys" step in Supabase. +4. **Cached tokens** - Old tokens are still being used after configuration changes. + +**Solutions:** +1. Verify your configuration: + - **Legacy keys**: "Use Supabase Auth" = **enabled** + JWT Secret filled in + - **New keys**: "Use Supabase Auth" = **disabled** + JWKS URI configured +2. Ensure your PowerSync instance and ALL client applications use the same JWT key type +3. If using new JWT signing keys, ensure you've completed the "Rotate Keys" step in Supabase +4. Clear all cached tokens by having users sign out and back in + ## 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). diff --git a/resources/troubleshooting/error-codes.mdx b/resources/troubleshooting/error-codes.mdx index 6cbfdf6e..f4025bbe 100644 --- a/resources/troubleshooting/error-codes.mdx +++ b/resources/troubleshooting/error-codes.mdx @@ -239,6 +239,11 @@ This does not include auth configuration errors on the service. - **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 configured in PowerSync. Ensure your PowerSync configuration and all client applications use the same JWT key type. See [Migrating Between JWT Signing Key Types](/installation/authentication-setup/supabase-auth#migrating-between-jwt-signing-key-types). + 2. **Missing or invalid key ID (kid)**: The token's kid header doesn't match any keys in PowerSync's 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. From 8f9d5fb362080308d7249aef917f1b6806220f13 Mon Sep 17 00:00:00 2001 From: bean1352 Date: Wed, 14 Jan 2026 13:45:17 +0200 Subject: [PATCH 2/4] Added detailed explanations of JWT signing keys, including configuration steps for both legacy and new keys, migration guidance, and troubleshooting tips for common authentication errors. --- .../authentication-setup/supabase-auth.mdx | 230 ++++++++++++------ resources/troubleshooting/error-codes.mdx | 2 +- 2 files changed, 157 insertions(+), 75 deletions(-) diff --git a/installation/authentication-setup/supabase-auth.mdx b/installation/authentication-setup/supabase-auth.mdx index 7b6a5c60..b3d0dd6f 100644 --- a/installation/authentication-setup/supabase-auth.mdx +++ b/installation/authentication-setup/supabase-auth.mdx @@ -24,120 +24,202 @@ You can implement various types of auth: * 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 -PowerSync can verify Supabase JWTs using either the legacy JWT signing keys or the newer asymmetric JWT signing keys: +Supabase supports two types of JWT signing keys: -- **Legacy JWT signing keys**: Use the "Use Supabase Auth" checkbox and provide your JWT secret. PowerSync verifies tokens using HS256 symmetric signing. -- **JWT signing keys**: Manually configure JWKS authentication (do not use "Use Supabase Auth"). PowerSync verifies tokens using asymmetric public key cryptography. +| 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. | -### PowerSync Cloud instances: +PowerSync supports both methods. Which configuration you need depends on your Supabase project's JWT settings and your PowerSync deployment type. -#### Using Legacy JWT Signing Keys + +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. + + +## 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. + + + + ### 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**. + + + PowerSync auto-detects your Supabase project from the database connection string and configures the JWKS URI (`https://.supabase.co/auth/v1/.well-known/jwks.json`) and audience (`authenticated`) automatically. + + + + + ### 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**. + -1. In the [PowerSync Dashboard](https://dashboard.powersync.com/), select your project and instance and go to the **Client Auth** view. + + ### Manual JWKS Configuration -2. **Enable** the **"Use Supabase Auth"** checkbox. + 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) -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). + 1. In the [PowerSync Dashboard](https://dashboard.powersync.com/), go to the **Client Auth** view. -4. Paste the secret into the **"Supabase JWT Secret (optional) Legacy"** field. + 2. Leave the **"Use Supabase Auth"** checkbox **unchecked**. -5. Click **Save and Deploy** to apply the changes. + 3. Add a **JWKS URI**: + ``` + https://.supabase.co/auth/v1/.well-known/jwks.json + ``` + Replace `` with your Supabase project reference ID. -#### Using New JWT Signing Keys + 4. Add `authenticated` as an accepted **JWT audience**. + + 5. Click **Save and Deploy**. -"Use Supabase Auth" ONLY works with legacy JWT signing keys. If you're using Supabase's new JWT signing keys, you must use manual JWKS configuration instead. +If you skip adding the `authenticated` audience, you will see `PSYNC_S2105` errors ("JWT payload is missing a required claim 'aud'"). + + + +## Self-Hosted PowerSync + +For self-hosted PowerSync instances, configure authentication in your [`config.yaml`](/self-hosting/installation/powersync-service-setup#powersync-configuration). + + + + ### Using New JWT Signing Keys + + When using a standard Supabase connection string, PowerSync auto-detects your Supabase project: + + ```yaml + client_auth: + supabase: true + ``` + + PowerSync will automatically configure: + - **JWKS URI**: `https://.supabase.co/auth/v1/.well-known/jwks.json` + - **Audience**: `authenticated` + + You'll see a log message confirming the configuration: + ``` + Configured Supabase Auth with https://.supabase.co/auth/v1/.well-known/jwks.json + ``` + + + + ### Using Legacy JWT Signing Keys -1. In the [PowerSync Dashboard](https://dashboard.powersync.com/), select your project and instance and go to the **Client Auth** view. + For projects using legacy HS256 symmetric signing keys, provide your JWT secret: -2. **Disable** the **"Use Supabase Auth"** checkbox (or leave it unchecked). + ```yaml + client_auth: + supabase: true + supabase_jwt_secret: your-jwt-secret-here + ``` -3. Complete 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 Keys"** step. + Get your JWT secret from your Supabase project's [JWT settings](https://supabase.com/dashboard/project/_/settings/jwt). + -4. Add the custom JWKS URI: - - **JWKS URI**: `https://.supabase.co/auth/v1/.well-known/jwks.json` - - Replace `` with your actual Supabase project reference ID + + ### Manual JWKS Configuration -5. Add JWT audience: - - Add `authenticated` as an accepted JWT audience + 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 -6. Click **Save and Deploy** to apply the changes. + ```yaml + client_auth: + jwks_uri: https://.supabase.co/auth/v1/.well-known/jwks.json + audience: + - authenticated + ``` + + Replace `` with your Supabase project reference ID. -See this [Discord thread](https://discord.com/channels/1138230179878154300/1194710422960472175/1396878076683485205) for community discussion about using the new JWT signing keys. +When using manual configuration, do not set `supabase: true`. Use `jwks_uri` and `audience` directly. + + -### Self-hosted instances: +## Migrating from Legacy to New JWT Signing Keys -Configure via your [`config.yaml`](/self-hosting/installation/powersync-service-setup): +If you're migrating your Supabase project from legacy JWT signing keys to the new asymmetric keys: -**For legacy JWT signing keys:** -```yaml -client_auth: - supabase: true - supabase_jwt_secret: your-jwt-secret -``` +### Step 1: Complete the Supabase Migration -**For new JWT signing keys:** -```yaml -client_auth: - # Do NOT set supabase: true - it only works with legacy keys - jwks_uri: https://.supabase.co/auth/v1/.well-known/jwks.json - audience: - - authenticated -``` - -## Migrating Between JWT Signing Key Types +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. -Your JWT configuration must be consistent across your entire stack. If you're migrating between Supabase's legacy JWT signing keys and the new JWT signing keys, ensure all components are updated together. +The migration is not complete until you complete the "Rotate to asymmetric JWTs" step in Supabase. Skipping this step will cause authentication failures. -### Migrating from Legacy to New JWT Signing Keys +### Step 2: Update PowerSync Configuration + +**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). -To migrate from legacy JWT signing keys to the new asymmetric keys: +**For manual JWKS configurations:** +- Ensure your `jwks_uri` points to your Supabase JWKS endpoint. +- Verify the `authenticated` audience is configured. -1. **Complete 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) +### Step 3: Clear Cached Tokens -2. **Update your PowerSync configuration:** - - **Disable** the **"Use Supabase Auth"** checkbox (it only works with legacy keys) - - Add a custom JWKS URI: `https://.supabase.co/auth/v1/.well-known/jwks.json` - - Add `authenticated` as an accepted JWT audience - - Click **Save and Deploy** +Have all users sign out and sign back in. This ensures they receive new tokens signed with the asymmetric keys. -3. **Update all client applications:** - - Ensure all client apps are using the new Supabase API keys (not legacy keys) - - Update any hardcoded anon keys or service role keys +## Troubleshooting -4. **Clear cached tokens:** - - Have all users sign out and sign back in - - This ensures they're using tokens generated with the new signing keys +### PSYNC_S2101: Could not find an appropriate key in the keystore -### Common Migration Issues +This error indicates PowerSync cannot verify the JWT signature. Common causes: -**Error:** `PSYNC_S2101 - Could not find an appropriate key in the keystore` +| 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. | -This authentication error typically occurs when there's a mismatch between: -- The JWT signing key type used by your client app (legacy vs. new) -- The JWT configuration in your PowerSync instance +### PSYNC_S2105: JWT payload is missing a required claim "aud" -**Common causes:** -1. **Using "Use Supabase Auth" with new JWT signing keys** - This doesn't work. "Use Supabase Auth" ONLY supports legacy keys. -2. **Mismatched client and server keys** - Your client is using legacy keys while PowerSync is configured for new keys (or vice versa). -3. **Incomplete Supabase migration** - You haven't completed the "Rotate Keys" step in Supabase. -4. **Cached tokens** - Old tokens are still being used after configuration changes. +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. +``` -**Solutions:** -1. Verify your configuration: - - **Legacy keys**: "Use Supabase Auth" = **enabled** + JWT Secret filled in - - **New keys**: "Use Supabase Auth" = **disabled** + JWKS URI configured -2. Ensure your PowerSync instance and ALL client applications use the same JWT key type -3. If using new JWT signing keys, ensure you've completed the "Rotate Keys" step in Supabase -4. Clear all cached tokens by having users sign out and back in +This means PowerSync couldn't detect your Supabase project from the database connection string. Use [manual JWKS configuration](#manual-jwks-configuration) instead. ## Sync Rules diff --git a/resources/troubleshooting/error-codes.mdx b/resources/troubleshooting/error-codes.mdx index f4025bbe..c8df7842 100644 --- a/resources/troubleshooting/error-codes.mdx +++ b/resources/troubleshooting/error-codes.mdx @@ -240,7 +240,7 @@ This does not include auth configuration errors on the service. 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 configured in PowerSync. Ensure your PowerSync configuration and all client applications use the same JWT key type. See [Migrating Between JWT Signing Key Types](/installation/authentication-setup/supabase-auth#migrating-between-jwt-signing-key-types). + 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. 3. **Incorrect JWT secret or JWKS endpoint**: Verify your authentication configuration matches your auth provider's settings. From 30caef972a8dec9c17b17f572a4019e7cdddb8af Mon Sep 17 00:00:00 2001 From: Dean Braun <72529945+bean1352@users.noreply.github.com> Date: Thu, 15 Jan 2026 10:38:09 +0200 Subject: [PATCH 3/4] Update installation/authentication-setup/supabase-auth.mdx Co-authored-by: Joshua Brink --- installation/authentication-setup/supabase-auth.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/installation/authentication-setup/supabase-auth.mdx b/installation/authentication-setup/supabase-auth.mdx index b3d0dd6f..d7cdbe32 100644 --- a/installation/authentication-setup/supabase-auth.mdx +++ b/installation/authentication-setup/supabase-auth.mdx @@ -92,7 +92,7 @@ When using PowerSync Cloud with a Supabase-hosted database, PowerSync can auto-d 3. Add a **JWKS URI**: ``` - https://.supabase.co/auth/v1/.well-known/jwks.json + http://localhost:54321/auth/v1/.well-known/jwks.json ``` Replace `` with your Supabase project reference ID. From 17afca73b50c75d9d74c73c50cf9246cc5e13984 Mon Sep 17 00:00:00 2001 From: Dean Braun <72529945+bean1352@users.noreply.github.com> Date: Thu, 15 Jan 2026 10:38:18 +0200 Subject: [PATCH 4/4] Update installation/authentication-setup/supabase-auth.mdx Co-authored-by: Joshua Brink --- installation/authentication-setup/supabase-auth.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/installation/authentication-setup/supabase-auth.mdx b/installation/authentication-setup/supabase-auth.mdx index d7cdbe32..3f05976b 100644 --- a/installation/authentication-setup/supabase-auth.mdx +++ b/installation/authentication-setup/supabase-auth.mdx @@ -156,7 +156,7 @@ For self-hosted PowerSync instances, configure authentication in your [`config.y ```yaml client_auth: - jwks_uri: https://.supabase.co/auth/v1/.well-known/jwks.json + jwks_uri: http://localhost:54321/auth/v1/.well-known/jwks.json audience: - authenticated ```