Integrating With Supabase Auth
Edge Functions work with Supabase Auth.
This allows you to:
- Automatically identify users through Legacy JWT tokens
- Enforce Row Level Security policies
- Integrate with your existing auth flow
Setting up auth context
When a user makes a request to an Edge Function, you can use the Authorization header to set the Auth context in the Supabase client and enforce Row Level Security policies.
import { createClient } from 'npm:@supabase/supabase-js@2'
Deno.serve(async (req: Request) => {
const supabaseClient = createClient(
Deno.env.get('SUPABASE_URL') ?? '',
Deno.env.get('SUPABASE_ANON_KEY') ?? '',
// Create client with Auth context of the user that called the function.
// This way your row-level-security (RLS) policies are applied.
{
global: {
headers: { Authorization: req.headers.get('Authorization')! },
},
}
);
//...
})Note
This context setting happens in the Deno.serve() callback argument, so that the Authorization header is set for each individual request scope.
Fetching the user
By getting the JWT from the Authorization header, you can provide the token to getUser() to fetch the user object to obtain metadata for the signed-in user.
Deno.serve(async (req: Request) => {
// ...
const authHeader = req.headers.get('Authorization')!
const token = authHeader.replace('Bearer ', '')
const { data } = await supabaseClient.auth.getUser(token)
// ...
})Row Level Security
After initializing a Supabase client with the Auth context, all queries will be executed with the context of the user. For database queries, this means Row Level Security will be enforced.
import { createClient } from 'npm:@supabase/supabase-js@2'
Deno.serve(async (req: Request) => {
// ...
// This query respects RLS - users only see rows they have access to
const { data, error } = await supabaseClient.from('profiles').select('*');
if (error) {
return new Response('Database error', { status: 500 })
}
// ...
})Example
See the full example on GitHub.
// Follow this setup guide to integrate the Deno language server with your editor:
// https://deno.land/manual/getting_started/setup_your_environment
// This enables autocomplete, go to definition, etc.
import { withSupabase } from 'npm:@supabase/server@^1'
console.log(`Function "select-from-table-with-auth-rls" up and running!`)
export default {
fetch: withSupabase({ auth: 'user' }, async (req, ctx) => {
try {
// ctx.supabase runs queries as the authenticated user, so RLS applies.
// ctx.userClaims holds the verified user identity.
const { data, error } = await ctx.supabase.from('users').select('*')
if (error) throw error
return Response.json({ user: ctx.userClaims, data })
} catch (error) {
return Response.json({ error: error.message }, { status: 400 })
}
}),
}
// To invoke (auth: 'user' requires a signed-in user's access token):
// curl -i --location --request POST 'http://localhost:54321/functions/v1/select-from-table-with-auth-rls' \
// --header 'Authorization: Bearer <USER_ACCESS_TOKEN>' \
// --header 'Content-Type: application/json' \
// --data '{"name":"Functions"}'