Replies: 1 comment
-
You can't just add anything you want to the role claim. That has to be a real postgres role granted to You could use another claim in the jwt for special role and check that with auth.jwt()->'special_role' or similar. You can also use the app_metadata like you are doing. Both of those would not use the https://supabase.com/docs/guides/storage/schema/custom-roles |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Hi all, I am new to Supabase and trying to set up a private storage bucket where only users with an "Admin" role in their JWT can upload and manage files.
I’ve created the necessary policies, roles, and privileges in Supabase, but when I try to upload or retrieve files using the Supabase API, I keep getting authentication errors such as:
"permission denied to set role 'Admin'"
"new row violates row-level security policy"
"403 Unauthorized"
Despite my efforts, I can’t get Supabase Storage to recognize my JWT claims properly.
Here’s everything I’ve done step-by-step:
Created a Private Storage Bucket named Documents to store uploaded files.
I manually created the "Admin" role in Supabase to distinguish privileged users.
I enabled Row Level Security and added policies for the "Admin" role.
CREATE
POLICY "Allow only Admins to insert files"ON storage.objects
FOR INSERT
TO authenticated
WITH CHECK (
((auth.jwt() ->> 'role') = 'Admin')
OR ((auth.jwt() -> 'app_metadata' ->> 'role') = 'Admin')
``);`
I generated a custom JWT that includes role: "Admin" in the app_metadata.
const
jwt = require('jsonwebtoken');exports.getSupabaseToken = (userId, email, role = 'Admin', expirationTime = '2h') => {
return jwt.sign(
{
aud: "authenticated",
sub: userId,
email,
app_metadata: { role },
user_metadata: {},
role,
},
process.env.SUPABASE_JWT_SECRET,
{ expiresIn: expirationTime }
);
};
This is the decoded jwt
{
"aud": "authenticated",
"sub": "005f43c1-b7ad-4895-a6ba-6a26ff108d69",
"email": "[email protected]",
"app_metadata": {
"role": "Admin"
},
"user_metadata": {},
"role": "Admin",
"iat": 1740258968,
"exp": 1740345368
}
When I run in supabase:
SELECT auth.jwt();
I get NULL, which means Supabase is not recognizing the JWT from my request.
To test authentication, I tried cURL requests:
curl -X GET "https://gegsudafxipazfnenzrc.supabase.co/storage/v1/object/authenticated/Documents/ricevuta.pdf"
-H "apikey: <SUPABASE_ANON_KEY>"
-H "Authorization: Bearer <MY_JWT>"
Which gave me:
{
"statusCode": "403",
"error": "Unauthorized",
"message": "new row violates row-level security policy"
}
Or { "code": "42501", "message": "permission denied to set role "Admin"" }
Even though the JWT has role: "Admin", Supabase does not grant the "Admin" role dynamically.
This is how I pass the token to the client:
const
{ createClient } = require('@supabase/supabase-js');const supabase = createClient(process.env.SUPABASE_URL, process.env.SUPABASE_ANON_KEY, {
global: {
headers: {
Authorization:
Bearer ${supabaseToken}
}
}
});
I'm really stuck on this. I feel like I'm missing a key step in how Supabase reads JWT roles and applies policies. Any guidance would be amazing!⁰
Beta Was this translation helpful? Give feedback.
All reactions