Edge Functions

Integrating With Supabase Auth

Integrate Supabase Auth with Edge Functions


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.

1
import { createClient } from 'npm:@supabase/supabase-js@2'
2
3
Deno.serve(async (req: Request) => {
4
const supabaseClient = createClient(
5
Deno.env.get('SUPABASE_URL') ?? '',
6
Deno.env.get('SUPABASE_ANON_KEY') ?? '',
7
// Create client with Auth context of the user that called the function.
8
// This way your row-level-security (RLS) policies are applied.
9
{
10
global: {
11
headers: { Authorization: req.headers.get('Authorization')! },
12
},
13
}
14
);
15
16
//...
17
})

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 logged in user.

1
Deno.serve(async (req: Request) => {
2
// ...
3
const authHeader = req.headers.get('Authorization')!
4
const token = authHeader.replace('Bearer ', '')
5
const { data } = await supabaseClient.auth.getUser(token)
6
// ...
7
})

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.

1
import { createClient } from 'npm:@supabase/supabase-js@2'
2
3
Deno.serve(async (req: Request) => {
4
// ...
5
// This query respects RLS - users only see rows they have access to
6
const { data, error } = await supabaseClient.from('profiles').select('*');
7
8
if (error) {
9
return new Response('Database error', { status: 500 })
10
}
11
12
// ...
13
})

Example#

See the full example on GitHub.

1
// Follow this setup guide to integrate the Deno language server with your editor:
2
// https://deno.land/manual/getting_started/setup_your_environment
3
// This enables autocomplete, go to definition, etc.
4
5
import { createClient } from 'npm:supabase-js@2'
6
// New approach (v2.95.0+)
7
import { corsHeaders } from 'jsr:@supabase/supabase-js@2/cors'
8
// For older versions:
9
// import { corsHeaders } from '../_shared/cors.ts'
10
11
console.log(`Function "select-from-table-with-auth-rls" up and running!`)
12
13
Deno.serve(async (req: Request) => {
14
// This is needed if you're planning to invoke your function from a browser.
15
if (req.method === 'OPTIONS') {
16
return new Response('ok', { headers: corsHeaders })
17
}
18
19
try {
20
// Create a Supabase client with the Auth context of the logged in user.
21
const supabaseClient = createClient(
22
// Supabase API URL - env var exported by default.
23
Deno.env.get('SUPABASE_URL') ?? '',
24
// Supabase API ANON KEY - env var exported by default.
25
Deno.env.get('SUPABASE_ANON_KEY') ?? '',
26
// Create client with Auth context of the user that called the function.
27
// This way your row-level-security (RLS) policies are applied.
28
{
29
global: {
30
headers: { Authorization: req.headers.get('Authorization')! },
31
},
32
}
33
)
34
35
// First get the token from the Authorization header
36
const token = req.headers.get('Authorization').replace('Bearer ', '')
37
38
// Now we can get the session or user object
39
const {
40
data: { user },
41
} = await supabaseClient.auth.getUser(token)
42
43
// And we can run queries in the context of our authenticated user
44
const { data, error } = await supabaseClient.from('users').select('*')
45
if (error) throw error
46
47
return new Response(JSON.stringify({ user, data }), {
48
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
49
status: 200,
50
})
51
} catch (error) {
52
return new Response(JSON.stringify({ error: error.message }), {
53
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
54
status: 400,
55
})
56
}
57
})
58
59
// To invoke:
60
// curl -i --location --request POST 'http://localhost:54321/functions/v1/select-from-table-with-auth-rls' \
61
// --header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24ifQ.625_WdcF3KHqz5amU0x2X5WWHP-OEs_4qj0ssLNHzTs' \
62
// --header 'Content-Type: application/json' \
63
// --data '{"name":"Functions"}'
View source