Reputation: 35
In a NextJS project I'm trying to add a stripe_customer_id to a Supabase user when they first sign up.
I can get this working fine when RLS isn't enabled but I need RLS to hide user data from anyone who isn't authenticated.
Can anyone help with what RLS policy I need to write to allow the create-stripe-customer api to update the customer_id column in Supabase?
Below is the create-stripe-customer (the file that works when RLS isn't enabled but not when RLS is enabled)
import initStripe from "stripe";
import { supabase } from "../../utils/supabaseClient";
const handler = async (req, res) => {
if (req.query.API_ROUTE_SECRET !== process.env.API_ROUTE_SECRET) {
return res.status(401).send('You are not authorized to call the API');
}
const stripe = initStripe(process.env.STRIPE_SECRET_KEY);
const customer = await stripe.customers.create({
email: req.body.record.email,
});
console.log("REQUEST-", req.body.record.id);
console.log("CUST ID-", customer.id);
await supabase
.from("profiles")
.update({
stripe_customer: customer.id,
})
.eq("id", req.body.record.id);
res.send({ message: `stripe customer creaded: ${customer.id}` });
console.log("TESTTESTTEST");
};
export default handler;
Upvotes: 0
Views: 1149
Reputation: 1152
To append to this, you should store the Stripe customer ID in a private table that only your SERVICE_ROLE
key can access. The client-side, even if the user is authenticated, should never be able to modify this, as they could change their own customer ID.
So make sure to store this in a secure table that only your server-side code can access.
Create a private mapping table: https://github.com/vercel/nextjs-subscription-payments/blob/main/schema.sql#L34-L45
/**
* CUSTOMERS
* Note: this is a private table that contains a mapping of user IDs to Stripe customer IDs.
*/
create table customers (
-- UUID from auth.users
id uuid references auth.users not null primary key,
-- The user's customer ID in Stripe. User must not be able to update this.
stripe_customer_id text
);
alter table customers enable row level security;
-- No policies as this is a private table that the user must not have access to.
Use your SERVICE_ROLE
key in a secure server side environment to access this private table: https://github.com/vercel/nextjs-subscription-payments/blob/main/utils/supabase-admin.ts#L7-L12
// Note: supabaseAdmin uses the SERVICE_ROLE_KEY which you must only use in a secure server-side context
// as it has admin priviliges and overwrites RLS policies!
const supabaseAdmin = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL || '',
process.env.SUPABASE_SERVICE_ROLE_KEY || ''
);
Upvotes: 1
Reputation: 18680
When updating data on Supabase, using the service role key instead of the anon key to create Supabase client will allow you to bypass row-level security policies.
You can find your service role key just below your anon key in your Supabase dashboard. Here is a video explaining how to use service role key to bypass RLS. https://egghead.io/lessons/supabase-use-the-supabase-service-key-to-bypass-row-level-security
Upvotes: 1