Service key client seems to be passing around a session

I'm getting this using the service key server side to insert data.
import { createClient as createServerClient } from '@supabase/supabase-js'

export const createClient = () =>
createServerClient<Database>(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.SUPABASE_SERVICE_ROLE_KEY!, {
auth: {
persistSession: false,
autoRefreshToken: false,
detectSessionInUrl: false
}
}
)
import { createClient as createServerClient } from '@supabase/supabase-js'

export const createClient = () =>
createServerClient<Database>(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.SUPABASE_SERVICE_ROLE_KEY!, {
auth: {
persistSession: false,
autoRefreshToken: false,
detectSessionInUrl: false
}
}
)
As I understand it the service key bypasses RLS? Or do you still need to add some kind of policy? Currently I have RLS enabled without any policies attached for this table. I basically want to restrict access completely to this table unless the service key is used.
35 Replies
garyaustin
garyaustin•2y ago
You can't use auth-helpers clients for service role. Use supabase-js regular client.
Music has the right to children
@supabase/supabase-js this is the regular client no?
garyaustin
garyaustin•2y ago
Oh sorry the name you gave it sounds like an auth-helpers client.
Music has the right to children
No worries
garyaustin
garyaustin•2y ago
What is the error you are getting on the insert? Do you use Prisma? Double check your service role.
Music has the right to children
šŸš€ ~ file: route.ts:116 ~ const{error:insertTokenError}=awaitsupabase.from ~ insertTokenError: {
code: '42501',
details: null,
hint: null,
message: 'new row violates row-level security policy for table "token"'
}
šŸš€ ~ file: route.ts:116 ~ const{error:insertTokenError}=awaitsupabase.from ~ insertTokenError: {
code: '42501',
details: null,
hint: null,
message: 'new row violates row-level security policy for table "token"'
}
garyaustin
garyaustin•2y ago
K so it is not grants. Are you signing in a user into the same client later?
Music has the right to children
Not using Prisma I just verified that the service role key is correct
garyaustin
garyaustin•2y ago
Somewhere you are either setting anon key into the client making the call or a user jwt is getting set into the client which will override the key. I've never seen an RLS error from service role helping people here. It starts out like this, but in the end somehow another token is getting sent out in the call. You can add an rls policy for TO anon and true as the policy. If that fails use TO authenticated and true. One of those will likely work and point which way is going wrong.
Music has the right to children
Tried to set anon: true, same error. Tried to set auth: true, worked.
garyaustin
garyaustin•2y ago
authenticated? If so you are signing in a user into that client somehow. You can't share clients.
Music has the right to children
Hmm odd, I mean at this stage there's no user signed in this specific flow. This is the sign up flow, I'm however passing a JWT token to this endpoint (that's not related to Supabase auth).
garyaustin
garyaustin•2y ago
If you set the authorization header for this client to a jwt then it is no longer service role. service_role can't be used with a user session at all. You have the right auth flags set to avoid getting sessions from the url or local storage.
Music has the right to children
Oh hmm ok I guess this could be the issue. The thing is that we have a flow where the user pays on stripe before signing up. Paid users retrieve an email with a link containing a JWT token. Once clicked they end up on a protected route where the form is connected to this endpoint.
garyaustin
garyaustin•2y ago
You really should use two separate clients.
Music has the right to children
I'm not following sorry
garyaustin
garyaustin•2y ago
You should do serviceRoleClient = createClient(blah) And serverClient = createClient(blah) Each is an object that holds state. I think you might be sharing the object with the way you are doing your create and imports. But I don't do server side stuff myself.
Music has the right to children
Ah I have 4 different utility functions:
supabase/
┣ client.ts
┣ middleware.ts
┣ server-service.ts
ā”— server.ts
supabase/
┣ client.ts
┣ middleware.ts
┣ server-service.ts
ā”— server.ts
garyaustin
garyaustin•2y ago
This is where I bow out. You may need to ask a specific question on your environment and the way you are setting up the client if you don't figure out. I just know enough to spot issues from helping those of you do the serverside stuff here.
Music has the right to children
There's only one client used in this endpoint and it's the server-service
garyaustin
garyaustin•2y ago
That won't work for service role. As soon as the object gets a user session in from elsewhere it becomes that user.
Music has the right to children
It's this one:
import { createClient as createServerClient } from '@supabase/supabase-js'

export const createClient = () =>
createServerClient<Database>(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.SUPABASE_SERVICE_ROLE_KEY!, {
auth: {
persistSession: false,
autoRefreshToken: false,
detectSessionInUrl: false
}
}
)
import { createClient as createServerClient } from '@supabase/supabase-js'

export const createClient = () =>
createServerClient<Database>(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.SUPABASE_SERVICE_ROLE_KEY!, {
auth: {
persistSession: false,
autoRefreshToken: false,
detectSessionInUrl: false
}
}
)
Music has the right to children
According to:
No description
garyaustin
garyaustin•2y ago
It is clear your service role client is being used somewhere else as it is getting a session in from a user. It can't be shared anywhere else. createClient creates an object to store state. If you reuse the object elsewhere then it will get the user state. Next time you use it where you expect it to be service role, it won't be. It will be an authenticated user.
Music has the right to children
Only used server-side
No description
garyaustin
garyaustin•2y ago
Silentworks is saying the same thing. The auth-helpers supabase clients can't be shared for service role.
Music has the right to children
And the env variable is only used in server-service
No description
garyaustin
garyaustin•2y ago
Does inport createClient reuse the same client? I believe it would, so won't work. I believe you need to export two clients. One for service role and one for normal stuff.
Music has the right to children
My other util fn: client, server, middleware they all import client from @supabase/ssr So there is only one client that imports from @supabase/supabase-js
garyaustin
garyaustin•2y ago
OK. If you don't use it somewhere else how is it getting a user session in it?
Music has the right to children
That's what I don't understand
garyaustin
garyaustin•2y ago
I thought you just showed it being used in several places. But as I said I don't know auth-helpers or server environments to figure out what you are doing. Someone who uses those might be able to explain exactly what you are doing to cause the session to get there. I would ask a new question with that as the topic versus RLS. You have to be reusing that exported client somewhere with a session in it. As soon as that happens it is no longer a service role client.
Music has the right to children
Ok cool! I will create a different topic for this. Thanks a lot for the help!
garyaustin
garyaustin•2y ago
Just want to make clear based on your change. The service key client will absolutely pass around a session anywhere you use it. The issue is some where it is getting the session put in it. That is what you have to solve.
Music has the right to children
Found the issue. I forgot about await supabase.auth.signUp... in the same endpoint. It returns a session. Thanks!

Did you find this page helpful?