Deine Edge Function läuft lokal – aber aus dem Browser oder per fetch kommt nur:
{"code":401,"message":"Invalid JWT"}
Oder: Missing authorization header. In diesem Guide behebst du den 401-Fehler Schritt für Schritt – inklusive wann du die JWT-Prüfung absichtlich abschaltest.
Das Problem: Warum Edge Functions 401 zurückgeben
Supabase Edge Functions können vor deinem Code eine JWT-Prüfung ausführen. Schlägt die fehl, läuft deine Function gar nicht – du siehst nur 401 von der Plattform.
Typische Auslöser:
- Kein
Authorization: Bearer …Header - Anon-Key statt User-Access-Token (oder umgekehrt)
- Abgelaufene Session / ungültiger JWT
- Function erwartet Auth, Aufruf kommt von Webhook/Cron ohne Token
- Neue asymmetric Keys vs. Legacy-JWT-Check
Die Lösung: Auth-Header oder Verify abschalten
Schritt 1: Korrekt mit Session aufrufen
const { data: { session } } = await supabase.auth.getSession()
const res = await fetch(
`${process.env.NEXT_PUBLIC_SUPABASE_URL}/functions/v1/my-function`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${session?.access_token}`,
apikey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
},
body: JSON.stringify({ hello: 'world' }),
}
)
Ohne gültige Session ist access_token leer – dann ist 401 erwartbar.
Schritt 2: Mit dem Functions-Client
const { data, error } = await supabase.functions.invoke('my-function', {
body: { hello: 'world' },
})
// Der JS-Client setzt Authorization automatisch aus der Session
Schritt 3: JWT-Verify für öffentliche Endpoints deaktivieren
Für Webhooks (Stripe, GitHub) oder öffentliche Endpoints brauchst du oft keinen User-JWT:
# config.toml (lokal) bzw. Dashboard → Edge Functions → Details
[functions.my-function]
verify_jwt = false
supabase functions deploy my-function --no-verify-jwt
Auth dann in der Function selbst prüfen (Secret-Header, Stripe-Signatur, …).
Schritt 4: In der Function selbst absichern
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'
import { corsHeaders } from '../_shared/cors.ts'
Deno.serve(async (req) => {
if (req.method === 'OPTIONS') {
return new Response('ok', { headers: corsHeaders })
}
const authHeader = req.headers.get('Authorization')
if (!authHeader) {
return new Response(JSON.stringify({ error: 'Missing authorization header' }), {
status: 401,
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
})
}
const supabase = createClient(
Deno.env.get('SUPABASE_URL')!,
Deno.env.get('SUPABASE_ANON_KEY')!,
{ global: { headers: { Authorization: authHeader } } }
)
const { data: { user }, error } = await supabase.auth.getUser()
if (error || !user) {
return new Response(JSON.stringify({ error: 'Invalid JWT' }), {
status: 401,
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
})
}
return new Response(JSON.stringify({ userId: user.id }), {
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
})
})
Häufige Fehler
- Nur apikey, kein Bearer: Viele Clients senden den Anon-Key, vergessen aber
Authorization. - Service-Role im Browser: Niemals. Für Server-to-Server: Verify aus + Secret, oder Service Role nur serverseitig.
- CORS + 401: Ohne CORS-Headers auf der 401-Response sieht der Browser oft nur einen CORS-Fehler. Siehe den CORS-Guide unten.
Troubleshooting Checklist
- ✅ Session vorhanden?
getSession()/getUser()loggen - ✅
Authorization: Bearer <access_token>gesetzt? - ✅
apikey-Header mit Anon-Key gesetzt? - ✅ Für Webhooks:
verify_jwt = false+ eigene Auth? - ✅ CORS-Headers auch auf 401-Responses?
Fazit
Invalid JWT / 401 bedeutet: Die Plattform (oder dein Code) akzeptiert den Token nicht. Entweder gültigen User-JWT mitsenden oder Verify bewusst deaktivieren und Auth selbst bauen – plus CORS nicht vergessen.
Weitere Ressourcen
- permission denied for table (42501)
- PGRST116: multiple (or no) rows
- RLS Insert-Fehler: new row violates row-level security policy
- Supabase Storage File Upload sicher implementieren
- Supabase Edge Functions CORS Fehler beheben
- Supabase Auth: Invalid login credentials
- Supabase: infinite recursion detected in policy
- Supabase Storage 403 RLS beim Upload
- ChatGPT Clone mit Edge Functions
- Supabase Edge Functions Auth
Immer noch 401 trotz Token? Kommentar da lassen – oft fehlt nur der Bearer-Header oder Verify ist noch an.
Kommentare