Pereiti prie turinio

Supabase raw_user_meta_data: kaip registracija tapo Owner

Supabase

Žiūrėti kaip MarkdownAtidaryti per ClaudeAtidaryti per ChatGPTAtidaryti per Perplexity

Klausimas taip pat nukopijuojamas. Jei pokalbis atsidaro tuščias, įklijuokite jį.

Trumpai

raw_user_meta_data laiko viską, ką naršyklė perdavė supabase.auth.signUp(). Vienoje produkcinėje programoje handle_new_user trigeris iš ten skaitė naujo vartotojo rolę, todėl bet kas galėjo užsiregistruoti su Owner rolės id ir perimti paskyrą. Pataisa: rolė imama iš lentelės, kurią rašo tik serveris ir kuri užpildoma prieš išsiunčiant kvietimą.

Tai nutiko audito įmonės laiko apskaitos programoje, Supabase programoje, kur kiekviena prieigos taisyklė gyvena duomenų bazėje. Klaida buvo trigeryje, kuris kiekvienam naujam vartotojui sukuria profilį.

Ką darė trigeris?

Supaprastintai jis atrodė taip:

create function public.handle_new_user()
returns trigger
language plpgsql
security definer set search_path = ''
as $$
declare
  _role_id uuid := (new.raw_user_meta_data ->> 'role_id')::uuid;
begin
  insert into public.profiles (id, full_name, role_id)
  values (new.id, new.raw_user_meta_data ->> 'full_name', _role_id);
  return new;
end;
$$;

Kvietimų srautas ten įrašydavo teisingą role_id, todėl įprastai naudojant viskas veikė. Tačiau raw_user_meta_data yra registracijos options.data, o jo turinį nusprendžia naršyklė:

await supabase.auth.signUp({
  email: 'me@example.com',
  password: '...',
  options: { data: { role_id: '<owner role uuid>' } },
})

Leidimų patikra savininkams grąžindavo true dar prieš žiūrėdama į bet ką kita, todėl vien šis laukas suteikdavo visišką paskyros kontrolę. Pati Supabase Users guide sako, kad vartotojo metaduomenų negalima naudoti RLS politikose ar autorizacijos logikoje, nes vartotojas gali juos keisti be jokių patikrų.

Iš kur atėjo naujo vartotojo rolė. handle_new_user trigeris prieš pataisą ir po jos. Prieš: kiekvienas, kas registruojasi: signUp options.data → raw_user_meta_data → handle_new_user → Owner rolė; Po: tik pakviesti žmonės: Kvietimo funkcija → pending_invites → handle_new_user → Kviestinė rolė.
Iš produkcinės Supabase programos registracijos trigerio, 2026 m. birželis.

Kas tai pataisė?

Dabar rolė imama iš privačios lentelės, prie kurios klientas neprieina:

create table private.pending_invites (
  email text primary key,
  role_id uuid,
  invited_by uuid,
  created_at timestamptz default now()
);
revoke all on table private.pending_invites from anon, authenticated;

Kvietimo funkcija veikia serveryje, patikrinus kviečiančiojo teisę. Ji pirmiausia įrašo laukiantį kvietimą ir tik tada sukuria kvietimo nuorodą. Trigeris suranda rolę pagal el. paštą ir ištrina eilutę. Vardas vis dar ateina iš metaduomenų, ir tai gerai: tai rodoma informacija.

Eilės tvarka svarbi. Kvietimas vartotoją sukuria iš karto: Supabase Users guide pažymi, kad naujo el. pašto pakvietimas sukuria nepatvirtintą vartotoją. Trigeris suveikia tuo metu, todėl laukiančios eilutės turi jau egzistuoti.

Kaip patikrinti savo programą?

Atidarykite savo handle_new_user funkciją ar bet kurį trigerį ant auth.users ir ieškokite raw_user_meta_data. Vardas ir avataras iš ten tinka. Rolė, įmonė, planas, nuomininkas ar bet kas kita, kas suteikia prieigą, turi ateiti iš lentelės arba iš raw_app_meta_data, kurio vartotojas pakeisti negali.

Tada išbandykite: užsiregistruokite per API, į options.data įrašę role_id arba role: 'admin'. Nauja paskyra neturi gauti nieko papildomo.

Tokia patikra yra pirmas mano RLS testavimo metodo žingsnis. Daugelio nuomininkų programoms taip pat žr. ką RLS praleidžia vartotojui dviejose org.. Kitos patikros, kurias atlieku kiekvienoje Supabase programoje, yra mano Lovable programos saugos sąraše. Pirmiausia dashboard’e žiūriu, kurias schemas pateikia Data API. Supabase saugumo patikra apima roles, teises, politikas ir autentifikacijos nustatymus pagal 45 OWASP Top 10:2025 taisykles, bet ne tai, ką trigeris nukopijuoja iš registracijos metaduomenų, todėl ši patikra lieka rankinė.

© 2026 Denys Zaichenko. Originalus straipsnis: https://madsalt.tech/lt/notes/supabase-raw-user-meta-data-role/