supabase / supabase-js

An isomorphic Javascript client for Supabase. Query your Supabase database, subscribe to realtime events, upload and download files, browse typescript examples, invoke postgres functions via rpc, invoke supabase edge functions, query pgvector.
https://supabase.com
MIT License
2.86k stars 220 forks source link

Supabase Client with service_role secret - JWSError JWSInvalidSignature #849

Open ethanfox opened 8 months ago

ethanfox commented 8 months ago

Bug report

Describe the bug

Creating a supabase client with the service_role secret returns a PGRST301 error. All .env variables have been verified. The correct .env variables are being used in the requests being made.

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

  1. Create a supabase client using the service_role secret instead of the public_anon key.
  2. Make a request with that client-server side.

Code to make client:

import type { Database } from "$lib/supabase-types";
import { createClient } from "@supabase/supabase-js";
import { ENV } from "./env";

export const supabaseAdmin = createClient<Database>(
    ENV.PUBLIC_SUPABASE_URL,
    ENV.SUPABASE_SERVICE_ROLE_KEY,
    {auth: {persistSession: false,autoRefreshToken: false,detectSessionInUrl: false,},},
);

Server function

export async function upsertProductRecord(stripeProduct: Stripe.Product) {
  const product = stripeProductSchema.parse(stripeProduct);
  const { error } = await supabaseAdmin.from("billing_products").upsert(product);

  if (error) {

    console.log("|| UPSERT ERROR ||",error);
    throw error;
  }
}

Expected behavior

Successful connection to supabase database to perform actions server side.

System information

Additional context

Using sveltekit-auth-helpers: 0.9.4

Error Response:

 {
  code: 'PGRST301',
  details: null,
  hint: null,
  message: 'JWSError JWSInvalidSignature'
}
saltcod commented 8 months ago

Hey @ethanfox — any rls policies? Do any other actions work? (insert/update/delete)?

DevJSter commented 8 months ago

It seems like you're encountering an issue with Supabase when creating a client using the service_role secret instead of the public_anon key. The error message you're receiving is 'PGRST301' with the details 'JWSError JWSInvalidSignature'. Let's try to resolve this issue step by step.

First, ensure that you've set up your environment variables correctly in your .env file. Double-check that ENV.PUBLIC_SUPABASE_URL and ENV.SUPABASE_SERVICE_ROLE_KEY contain the correct values.

Next, let's look at your createClient function and server-side code. It appears that you're using the Supabase JavaScript client library (@supabase/supabase-js). Ensure that you have installed the correct version of this library (v2.21.0).

In your createClient function, you are passing the ENV.SUPABASE_SERVICE_ROLE_KEY as the second parameter, which should be the service role secret. This seems correct.

Now, let's focus on the error message 'JWSInvalidSignature.' This error suggests that there might be an issue with the JWT (JSON Web Token) signature. Here are a few steps to investigate and resolve this:

  1. Regenerate Service Role Secret: Ensure that the service role secret you are using is valid and hasn't expired. If you suspect any issues with it, regenerate a new one from the Supabase dashboard.

  2. Check Permissions: Make sure that the service role has the necessary permissions to perform the upsert operation on the billing_products table. You can check and modify these permissions in your Supabase dashboard under "SQL Editor."

  3. Update Supabase Client: Check if there are any updates to the Supabase client library. It's a good practice to keep your dependencies up-to-date.

  4. Error Handling: In your code, you are logging the error message, but you might want to log more details to help with debugging. Modify your error handling to log additional information, such as the response from Supabase.

Here's an updated version of your server function with improved error logging:

export async function upsertProductRecord(stripeProduct: Stripe.Product) {
  const product = stripeProductSchema.parse(stripeProduct);
  const { error, data, status } = await supabaseAdmin
    .from("billing_products")
    .upsert(product);

  if (error) {
    console.error("Error during upsert:", error.message);
    console.error("Supabase Status Code:", status);
    console.error("Supabase Error Details:", error.details);
    throw error;
  }

  // Handle success or use the data variable if needed.
  return data;
}

By logging more details about the error, you should be able to get a better understanding of what's causing the 'JWSInvalidSignature' error and take appropriate actions to resolve it.

Remember to perform these steps and ensure that your environment variables, permissions, and library versions are all correct. If the issue persists, consider reaching out to Supabase support for further assistance, as it could be related to specific configurations in your Supabase project.

ethanfox commented 8 months ago

My variables are correct.

  1. Tried that didn't work
  2. The service role key bypasses RLS by default.
  3. Up to date
  4. Error during upsert: JWSError JWSInvalidSignature
    Supabase Status Code: 401
    Supabase Error Details: null
    {
    code: 'PGRST301',
    details: null,
    hint: null,
    message: 'JWSError JWSInvalidSignature'
    }

Also, I did reach out to Supabase Support and they said this is out of their "scope". 🤷‍♂️

DevJSter commented 8 months ago

Alright!

ethanfox commented 8 months ago

Alright!

So now what? Do you have any other idea why this wouldn't be working?

DevJSter commented 8 months ago

ossible Solutions:

Double-Check Secret Key: Ensure that the service role secret key you're using matches the one provided by Supabase. Even a small difference in the key can lead to authentication errors.

JWT Configuration: Verify that your JWT (JSON Web Token) configuration in Supabase is set up correctly. Check the algorithm used for signing and verifying JWTs and make sure it aligns with your code.

Library Compatibility: Ensure that the JWT library or tool you're using in your code (e.g., jsonwebtoken) is compatible with the JWT settings and key format used by Supabase. Make sure you're using the latest version of the library.

Environment Variables: Review your environment variables meticulously. Even a minor typo or special character can cause issues. Recheck that ENV.PUBLIC_SUPABASE_URL and ENV.SUPABASE_SERVICE_ROLE_KEY are correctly set.

Service Role Permissions: While the service role key bypasses Row-Level Security (RLS), confirm that the service role itself has the necessary permissions to access tables and perform the 'upsert' operation.

Supabase Project Settings: Look into your Supabase project settings and custom security rules. There could be configurations affecting JWT verification.

Supabase Version: Ensure you are using a compatible version of Supabase. Check for updates or bug fixes related to JWT authentication in newer releases.

Logging and Debugging: Implement more detailed logging during the JWT verification process. Log the token, headers, payloads, and any error details to gain insights into what's going wrong.

If after revisiting these aspects the issue persists, it might be worth reaching out to a security expert or seeking assistance from Supabase's community or support channels. They might offer specific guidance tailored to your Supabase setup to help you resolve this authentication problem.

nowfred commented 1 month ago

@ethanfox did you ever resolve this? We have the exact same issue happening to us serverside, is extremely unhelpful.

Also, when our serverside instances trigger this issue the ensuing 'reauthentication' storm (relatively small number of instances, less than 50) trigger the 'authenticator' role to effectively lock up the entire database.