---
title: "Supabase raw_user_meta_data: rekisteröityjästä tuli Owner"
description: "handle_new_user-triggeri otti role_id:n kentästä raw_user_meta_data, jonka selain asettaa. Miten kuka tahansa tuli Owneriksi, korjaus ja minuutin tarkistus."
url: "https://madsalt.tech/fi/notes/supabase-raw-user-meta-data-role/"
author: "Denys Zaichenko"
language: "fi"
published: 2026-10-18
---

# Supabase raw_user_meta_data: rekisteröityjästä tuli Owner

TL;DR

`raw_user_meta_data` sisältää sen, minkä selain välitti kutsulle `supabase.auth.signUp()`. Yhdessä tuotantosovelluksessa `handle_new_user`-triggeri luki uuden käyttäjän roolin siitä, joten kuka tahansa pystyi rekisteröitymään Owner-roolin id:llä ja omistamaan tilin. Korjaus: rooli tulee taulusta, johon vain palvelin kirjoittaa, ja se täytetään ennen kutsun lähettämistä.

Tämä tapahtui [tilintarkastusyhtiön ajanseurantasovelluksessa](https://madsalt.tech/fi/work/audit-firm-time-tracking/), Supabase-sovelluksessa, jossa jokainen käyttöoikeussääntö on tietokannassa. Bugi oli triggerissä, joka luo profiilin jokaiselle uudelle käyttäjälle.

## Mitä triggeri teki?

Yksinkertaistettuna se näytti tältä:

```sql
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;
$$;
```

Kutsuprosessi laittoi sinne oikean `role_id`:n, joten normaalikäytössä se toimi. Mutta `raw_user_meta_data` on rekisteröitymisen `options.data`, ja selain päättää, mitä siihen tulee:

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

Oikeustarkistus palautti omistajille tosi ennen kuin katsoi mitään muuta, joten tuo yksi kenttä antoi täyden hallinnan tiliin. Supabasen oma [Users-opas](https://supabase.com/docs/guides/auth/users) sanoo, ettei käyttäjän metadataa saa käyttää RLS-politiikoissa tai valtuutuslogiikassa, koska käyttäjä voi muokata sitä ilman mitään tarkistuksia.

![Mistä uuden käyttäjän rooli tuli. handle_new_user-triggeri ennen korjausta ja sen jälkeen. Ennen: kuka tahansa rekisteröityjä: signUp options.data → raw_user_meta_data → handle_new_user → Owner-rooli; Jälkeen: vain kutsutut: Kutsufunktio → pending_invites → handle_new_user → Kutsuttu rooli.](https://madsalt.tech/charts/fi/supabase-raw-user-meta-data-role.svg)

*Tuotannossa olevan Supabase-sovelluksen rekisteröitymistriggeristä, kesäkuu 2026.*

## Mikä korjasi sen?

Rooli tulee nyt yksityisestä taulusta, johon asiakas ei pääse käsiksi:

```sql
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;
```

Kutsufunktio ajetaan palvelimella, kun kutsujan oikeus on tarkistettu. Se kirjoittaa ensin odottavan kutsun ja luo vasta sitten kutsulinkin. Triggeri hakee roolin sähköpostiosoitteella ja poistaa rivin. Nimi tulee edelleen metadatasta, mikä on kunnossa: se on näyttödataa.

Järjestyksellä on väliä. Kutsu luo käyttäjän heti: Supabasen [Users-opas](https://supabase.com/docs/guides/auth/users) toteaa, että uuden sähköpostin kutsuminen luo vahvistamattoman käyttäjän. Triggeri laukeaa sillä hetkellä, joten odottavan rivin on oltava jo olemassa.

## Miten tarkistat oman sovelluksesi?

Avaa `handle_new_user`-funktiosi tai mikä tahansa `auth.users`-taulun triggeri ja hae `raw_user_meta_data`. Nimi ja avatar sieltä ovat kunnossa. Rooli, yritys, paketti, vuokralainen tai mikä tahansa muu, joka antaa pääsyn, on otettava taulusta tai kentästä `raw_app_meta_data`, jota käyttäjä ei voi muuttaa.

Kokeile sitten: rekisteröidy API:n kautta antamalla `options.data`-kenttään `role_id` tai `role: 'admin'`. Uuden tilin ei pitäisi saada mitään ylimääräistä.

Tällainen tarkistus on [RLS-testausmenetelmäni](https://madsalt.tech/fi/blog/how-to-test-supabase-rls/) ensimmäinen askel. Monivuokraajaisille sovelluksille katso myös [mitä RLS ei huomaa kahden organisaation käyttäjän kohdalla](https://madsalt.tech/fi/notes/supabase-rls-user-in-two-organizations/). Muut tarkistukset, jotka teen jokaiselle Supabase-sovellukselle, ovat [Lovable-sovelluksen tietoturvatarkistuslistassani](https://madsalt.tech/fi/blog/lovable-app-security-checklist/). Ensimmäinen, jota katson Dashboardissa, on [mitkä skeemat Data API julkaisee](https://madsalt.tech/fi/notes/supabase-exposed-schemas/). [Supabase tietoturvatarkistus](https://madsalt.tech/fi/tools/supabase-security-check/) kattaa roolit, oikeudet, politiikat ja autentikointiasetukset 46 OWASP Top 10:2025 -säännön mukaan, ei sitä, mitä triggeri kopioi rekisteröitymismetadatasta, joten tämä pysyy käsin tehtävänä tarkistuksena.
